Commit d9e7e1b1 authored by Ondřej Zajíček's avatar Ondřej Zajíček

Adds support for iface link detection to OSPF.

parent fe181e7c
......@@ -192,13 +192,14 @@ ospf_iface_item:
| TYPE POINTOPOINT { OSPF_PATT->type = OSPF_IT_PTP ; }
| STRICT NONBROADCAST bool { OSPF_PATT->strictnbma = $3 ; }
| STUB bool { OSPF_PATT->stub = $2 ; }
| LINK bool { OSPF_PATT->use_link = $2 ; }
| NEIGHBORS '{' ipa_list '}'
| AUTHENTICATION NONE { OSPF_PATT->autype = OSPF_AUTH_NONE ; }
| AUTHENTICATION SIMPLE { OSPF_PATT->autype = OSPF_AUTH_SIMPLE ; }
| AUTHENTICATION CRYPTOGRAPHIC { OSPF_PATT->autype = OSPF_AUTH_CRYPT ; }
| RX BUFFER LARGE { OSPF_PATT->rxbuf = OSPF_RXBUF_LARGE ; }
| RX BUFFER NORMAL { OSPF_PATT->rxbuf = OSPF_RXBUF_NORMAL ; }
| RX BUFFER expr { OSPF_PATT->rxbuf = $3 ; if ($3 < OSPF_RXBUF_MINSIZE) cf_error("Buffer size is too small") ; }
| RX BUFFER expr { OSPF_PATT->rxbuf = $3 ; if (($3 < OSPF_RXBUF_MINSIZE) || ($3 > OSPF_MAX_PKT_SIZE)) cf_error("Buffer size must be in range 256-65535"); }
| password_list
;
......@@ -275,6 +276,7 @@ ospf_iface_start:
OSPF_PATT->type = OSPF_IT_UNDEF;
OSPF_PATT->strictnbma = 0;
OSPF_PATT->stub = 0;
OSPF_PATT->use_link = 1;
init_list(&OSPF_PATT->nbma_list);
OSPF_PATT->autype = OSPF_AUTH_NONE;
reset_passwords();
......
This diff is collapsed.
......@@ -13,7 +13,7 @@
void ospf_iface_chstate(struct ospf_iface *ifa, u8 state);
void ospf_iface_sm(struct ospf_iface *ifa, int event);
struct ospf_iface *ospf_iface_find(struct proto_ospf *p, struct iface *what);
void ospf_iface_notify(struct proto *p, unsigned flags, struct iface *iface);
void ospf_if_notify(struct proto *p, unsigned flags, struct iface *iface);
void ospf_ifa_notify(struct proto *p, unsigned flags, struct ifa *a);
void ospf_iface_info(struct ospf_iface *ifa);
void ospf_iface_shutdown(struct ospf_iface *ifa);
......
......@@ -269,7 +269,7 @@ ospf_init(struct proto_config *c)
p->reload_routes = ospf_reload_routes;
p->accept_ra_types = RA_OPTIMAL;
p->rt_notify = ospf_rt_notify;
p->if_notify = ospf_iface_notify;
p->if_notify = ospf_if_notify;
p->ifa_notify = ospf_ifa_notify;
p->rte_better = ospf_rte_better;
p->rte_same = ospf_rte_same;
......@@ -728,7 +728,7 @@ ospf_reconfigure(struct proto *p, struct proto_config *c)
}
/* POLL TIMER */
if (oldip->pollint != newip->pollint)
if ((oldip->pollint != newip->pollint) && ifa->poll_timer)
{
ifa->pollint = newip->helloint;
ifa->poll_timer->recurrent = ifa->pollint;
......@@ -758,6 +758,15 @@ ospf_reconfigure(struct proto *p, struct proto_config *c)
ospf_iface_change_mtu(po, ifa);
}
/* LINK */
if (oldip->use_link != newip->use_link)
{
ifa->use_link = newip->use_link;
if (!(ifa->iface->flags & IF_LINK_UP))
ospf_iface_sm(ifa, ifa->use_link ? ISM_LOOP : ISM_UNLOOP);
}
/* strict nbma */
if ((oldip->strictnbma == 0) && (newip->strictnbma != 0))
{
......@@ -819,7 +828,7 @@ ospf_reconfigure(struct proto *p, struct proto_config *c)
}
/* WAIT */
if (oldip->waitint != newip->waitint)
if ((oldip->waitint != newip->waitint) && ifa->wait_timer)
{
ifa->waitint = newip->waitint;
if (ifa->wait_timer->expires != 0)
......@@ -890,7 +899,7 @@ ospf_reconfigure(struct proto *p, struct proto_config *c)
}
if (!found)
{
nb1 = mb_alloc(p->pool, sizeof(struct nbma_node));
nb1 = mb_alloc(ifa->pool, sizeof(struct nbma_node));
nb1->ip = nb2->ip;
nb1->eligible = nb2->eligible;
add_tail(&ifa->nbma_list, NODE nb1);
......
......@@ -162,7 +162,7 @@ struct ospf_iface
struct iface *iface; /* Nest's iface */
struct ifa *addr; /* IP prefix associated with that OSPF iface */
struct ospf_area *oa;
struct object_lock *lock;
pool *pool;
sock *sk; /* IP socket (for DD ...) */
list neigh_list; /* List of neigbours */
u32 cost; /* Cost of iface */
......@@ -187,8 +187,8 @@ struct ospf_iface
#endif
ip_addr drip; /* Designated router */
u32 drid;
ip_addr bdrip; /* Backup DR */
u32 drid;
u32 bdrid;
#ifdef OSPFv3
......@@ -207,7 +207,7 @@ struct ospf_iface
u8 stub; /* Inactive interface */
u8 state; /* Interface state machine */
#define OSPF_IS_DOWN 0 /* Not working */
#define OSPF_IS_LOOP 1 /* Should never happen */
#define OSPF_IS_LOOP 1 /* Iface with no link */
#define OSPF_IS_WAITING 2 /* Waiting for Wait timer */
#define OSPF_IS_PTP 3 /* PTP operational */
#define OSPF_IS_DROTHER 4 /* I'm on BCAST or NBMA and I'm not DR */
......@@ -243,7 +243,8 @@ struct ospf_iface
#define OSPF_I_LL 2 /* Missing link-local address (OSPFv3) */
u8 sk_spf; /* Socket is a member of SPFRouters group */
u8 sk_dr; /* Socket is a member of DRouters group */
u32 rxbuf;
u16 rxbuf; /* Buffer size */
u8 use_link; /* Whether iface link change is used */
};
struct ospf_md5
......@@ -678,8 +679,8 @@ struct ospf_neighbor
#define ISM_WAITF 1 /* Wait timer fired */
#define ISM_BACKS 2 /* Backup seen */
#define ISM_NEICH 3 /* Neighbor change */
// #define ISM_LOOP 4 /* Loop indicated */
// #define ISM_UNLOOP 5 /* Unloop indicated */
#define ISM_LOOP 4 /* Link down */
#define ISM_UNLOOP 5 /* Link up */
#define ISM_DOWN 6 /* Interface down */
/* Definitions for neighbor state machine */
......@@ -751,7 +752,8 @@ struct ospf_iface_patt
u32 strictnbma;
u32 stub;
u32 vid;
u32 rxbuf;
u16 rxbuf;
u8 use_link;
#define OSPF_RXBUF_NORMAL 0
#define OSPF_RXBUF_LARGE 1
#define OSPF_RXBUF_MINSIZE 256 /* Minimal allowed size */
......
......@@ -241,9 +241,6 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 *length)
if ((ifa->oa != oa) || (ifa->state == OSPF_IS_DOWN))
continue;
/* BIRD does not support interface loops */
ASSERT(ifa->state != OSPF_IS_LOOP);
switch (ifa->type)
{
case OSPF_IT_PTP: /* RFC2328 - 12.4.1.1 */
......@@ -303,11 +300,24 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 *length)
continue;
ln = lsab_alloc(po, sizeof(struct ospf_lsa_rt_link));
ln->type = LSART_STUB;
ln->id = ipa_to_u32(ifa->addr->prefix);
ln->data = ipa_to_u32(ipa_mkmask(ifa->addr->pxlen));
ln->metric = ifa->cost;
ln->padding = 0;
if (ifa->state == OSPF_IS_LOOP)
{
/* Host stub entry */
ln->type = LSART_STUB;
ln->id = ipa_to_u32(ifa->addr->ip);
ln->data = 0xffffffff;
ln->metric = 0;
ln->padding = 0;
}
else
{
/* Network stub entry */
ln->type = LSART_STUB;
ln->id = ipa_to_u32(ifa->addr->prefix);
ln->data = ipa_to_u32(ipa_mkmask(ifa->addr->pxlen));
ln->metric = ifa->cost;
ln->padding = 0;
}
i++;
}
......@@ -384,9 +394,6 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 *length)
if ((ifa->oa != oa) || (ifa->state == OSPF_IS_DOWN))
continue;
/* BIRD does not support interface loops */
ASSERT(ifa->state != OSPF_IS_LOOP);
/* RFC5340 - 4.4.3.2 */
switch (ifa->type)
{
......@@ -1144,6 +1151,13 @@ update_link_lsa(struct ospf_iface *ifa)
ifa->origlink = 0;
}
static inline void
lsa_put_prefix(struct proto_ospf *po, ip_addr prefix, u32 pxlen, u32 cost)
{
put_ipv6_prefix(lsab_alloc(po, IPV6_PREFIX_SPACE(pxlen)), prefix, pxlen,
(pxlen < MAX_PREFIX_LENGTH) ? 0 : OPT_PX_LA, cost);
}
static void *
originate_prefix_rt_lsa_body(struct ospf_area *oa, u16 *length)
{
......@@ -1154,7 +1168,6 @@ originate_prefix_rt_lsa_body(struct ospf_area *oa, u16 *length)
int host_addr = 0;
int net_lsa;
int i = 0;
u8 flags;
ASSERT(po->lsab_used == 0);
lp = lsab_allocz(po, sizeof(struct ospf_lsa_prefix));
......@@ -1189,12 +1202,14 @@ originate_prefix_rt_lsa_body(struct ospf_area *oa, u16 *length)
configured_stubnet(oa, a))
continue;
flags = (a->pxlen < MAX_PREFIX_LENGTH) ? 0 : OPT_PX_LA;
put_ipv6_prefix(lsab_alloc(po, IPV6_PREFIX_SPACE(a->pxlen)),
a->ip, a->pxlen, flags, ifa->cost);
if (ifa->state == OSPF_IS_LOOP)
lsa_put_prefix(po, a->ip, MAX_PREFIX_LENGTH, 0);
else
lsa_put_prefix(po, a->prefix, a->pxlen, ifa->cost);
i++;
if (flags & OPT_PX_LA)
if ((ifa->state == OSPF_IS_LOOP) ||
(a->pxlen == MAX_PREFIX_LENGTH))
host_addr = 1;
}
}
......@@ -1203,8 +1218,7 @@ originate_prefix_rt_lsa_body(struct ospf_area *oa, u16 *length)
which will be used as a vlink endpoint. */
if (oa->ac && !EMPTY_LIST(oa->ac->vlink_list) && !host_addr && vlink_addr)
{
put_ipv6_prefix(lsab_alloc(po, IPV6_PREFIX_SPACE(MAX_PREFIX_LENGTH)),
vlink_addr->ip, MAX_PREFIX_LENGTH, OPT_PX_LA, 0);
lsa_put_prefix(po, vlink_addr->ip, MAX_PREFIX_LENGTH, 0);
i++;
}
......@@ -1213,9 +1227,7 @@ originate_prefix_rt_lsa_body(struct ospf_area *oa, u16 *length)
WALK_LIST(sn, oa->ac->stubnet_list)
if (!sn->hidden)
{
flags = (sn->px.len < MAX_PREFIX_LENGTH) ? 0 : OPT_PX_LA;
put_ipv6_prefix(lsab_alloc(po, IPV6_PREFIX_SPACE(sn->px.len)),
sn->px.addr, sn->px.len, flags, sn->cost);
lsa_put_prefix(po, sn->px.addr, sn->px.len, sn->cost);
i++;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment