Adds support for iface link detection to OSPF.
This commit is contained in:
parent
fe181e7c63
commit
d9e7e1b13d
6 changed files with 203 additions and 171 deletions
|
@ -192,13 +192,14 @@ ospf_iface_item:
|
||||||
| TYPE POINTOPOINT { OSPF_PATT->type = OSPF_IT_PTP ; }
|
| TYPE POINTOPOINT { OSPF_PATT->type = OSPF_IT_PTP ; }
|
||||||
| STRICT NONBROADCAST bool { OSPF_PATT->strictnbma = $3 ; }
|
| STRICT NONBROADCAST bool { OSPF_PATT->strictnbma = $3 ; }
|
||||||
| STUB bool { OSPF_PATT->stub = $2 ; }
|
| STUB bool { OSPF_PATT->stub = $2 ; }
|
||||||
|
| LINK bool { OSPF_PATT->use_link = $2 ; }
|
||||||
| NEIGHBORS '{' ipa_list '}'
|
| NEIGHBORS '{' ipa_list '}'
|
||||||
| AUTHENTICATION NONE { OSPF_PATT->autype = OSPF_AUTH_NONE ; }
|
| AUTHENTICATION NONE { OSPF_PATT->autype = OSPF_AUTH_NONE ; }
|
||||||
| AUTHENTICATION SIMPLE { OSPF_PATT->autype = OSPF_AUTH_SIMPLE ; }
|
| AUTHENTICATION SIMPLE { OSPF_PATT->autype = OSPF_AUTH_SIMPLE ; }
|
||||||
| AUTHENTICATION CRYPTOGRAPHIC { OSPF_PATT->autype = OSPF_AUTH_CRYPT ; }
|
| AUTHENTICATION CRYPTOGRAPHIC { OSPF_PATT->autype = OSPF_AUTH_CRYPT ; }
|
||||||
| RX BUFFER LARGE { OSPF_PATT->rxbuf = OSPF_RXBUF_LARGE ; }
|
| RX BUFFER LARGE { OSPF_PATT->rxbuf = OSPF_RXBUF_LARGE ; }
|
||||||
| RX BUFFER NORMAL { OSPF_PATT->rxbuf = OSPF_RXBUF_NORMAL ; }
|
| 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
|
| password_list
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -275,6 +276,7 @@ ospf_iface_start:
|
||||||
OSPF_PATT->type = OSPF_IT_UNDEF;
|
OSPF_PATT->type = OSPF_IT_UNDEF;
|
||||||
OSPF_PATT->strictnbma = 0;
|
OSPF_PATT->strictnbma = 0;
|
||||||
OSPF_PATT->stub = 0;
|
OSPF_PATT->stub = 0;
|
||||||
|
OSPF_PATT->use_link = 1;
|
||||||
init_list(&OSPF_PATT->nbma_list);
|
init_list(&OSPF_PATT->nbma_list);
|
||||||
OSPF_PATT->autype = OSPF_AUTH_NONE;
|
OSPF_PATT->autype = OSPF_AUTH_NONE;
|
||||||
reset_passwords();
|
reset_passwords();
|
||||||
|
|
|
@ -60,10 +60,7 @@ rxbufsize(struct ospf_iface *ifa)
|
||||||
static int
|
static int
|
||||||
ospf_sk_open(struct ospf_iface *ifa)
|
ospf_sk_open(struct ospf_iface *ifa)
|
||||||
{
|
{
|
||||||
sock *sk;
|
sock *sk = sk_new(ifa->pool);
|
||||||
struct proto *p = &ifa->oa->po->proto;
|
|
||||||
|
|
||||||
sk = sk_new(p->pool);
|
|
||||||
sk->type = SK_IP;
|
sk->type = SK_IP;
|
||||||
sk->dport = OSPF_PROTO;
|
sk->dport = OSPF_PROTO;
|
||||||
sk->saddr = IPA_NONE;
|
sk->saddr = IPA_NONE;
|
||||||
|
@ -162,72 +159,6 @@ ospf_sk_leave_dr(struct ospf_iface *ifa)
|
||||||
ifa->sk_dr = 0;
|
ifa->sk_dr = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
|
||||||
ospf_sk_close(struct ospf_iface *ifa)
|
|
||||||
{
|
|
||||||
ASSERT(ifa->sk);
|
|
||||||
|
|
||||||
rfree(ifa->sk);
|
|
||||||
ifa->sk = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ospf_iface_chstate - handle changes of interface state
|
|
||||||
* @ifa: OSPF interface
|
|
||||||
* @state: new state
|
|
||||||
*
|
|
||||||
* Many actions must be taken according to interface state changes. New network
|
|
||||||
* LSAs must be originated, flushed, new multicast sockets to listen for messages for
|
|
||||||
* %ALLDROUTERS have to be opened, etc.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
ospf_iface_chstate(struct ospf_iface *ifa, u8 state)
|
|
||||||
{
|
|
||||||
struct proto_ospf *po = ifa->oa->po;
|
|
||||||
struct proto *p = &po->proto;
|
|
||||||
u8 oldstate = ifa->state;
|
|
||||||
|
|
||||||
if (oldstate != state)
|
|
||||||
{
|
|
||||||
ifa->state = state;
|
|
||||||
|
|
||||||
if (ifa->type == OSPF_IT_VLINK)
|
|
||||||
{
|
|
||||||
OSPF_TRACE(D_EVENTS,
|
|
||||||
"Changing state of virtual link %R from \"%s\" into \"%s\".",
|
|
||||||
ifa->vid, ospf_is[oldstate], ospf_is[state]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
OSPF_TRACE(D_EVENTS,
|
|
||||||
"Changing state of iface: %s from \"%s\" into \"%s\".",
|
|
||||||
ifa->iface->name, ospf_is[oldstate], ospf_is[state]);
|
|
||||||
if (ifa->iface->flags & IF_MULTICAST)
|
|
||||||
{
|
|
||||||
if ((ifa->type != OSPF_IT_NBMA) && (ifa->ioprob == OSPF_I_OK) &&
|
|
||||||
((state == OSPF_IS_BACKUP) || (state == OSPF_IS_DR)))
|
|
||||||
ospf_sk_join_dr(ifa);
|
|
||||||
else
|
|
||||||
ospf_sk_leave_dr(ifa);
|
|
||||||
|
|
||||||
if ((oldstate == OSPF_IS_DR) && (ifa->net_lsa != NULL))
|
|
||||||
{
|
|
||||||
ifa->net_lsa->lsa.age = LSA_MAXAGE;
|
|
||||||
if (state >= OSPF_IS_WAITING)
|
|
||||||
{
|
|
||||||
ospf_lsupd_flush_nlsa(po, ifa->net_lsa);
|
|
||||||
}
|
|
||||||
if (can_flush_lsa(po))
|
|
||||||
flush_lsa(ifa->net_lsa, po);
|
|
||||||
ifa->net_lsa = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// FIXME flushling of link LSA
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ospf_iface_down(struct ospf_iface *ifa)
|
ospf_iface_down(struct ospf_iface *ifa)
|
||||||
{
|
{
|
||||||
|
@ -254,6 +185,15 @@ ospf_iface_down(struct ospf_iface *ifa)
|
||||||
ospf_neigh_remove(n);
|
ospf_neigh_remove(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ifa->hello_timer)
|
||||||
|
tm_stop(ifa->hello_timer);
|
||||||
|
|
||||||
|
if (ifa->poll_timer)
|
||||||
|
tm_stop(ifa->poll_timer);
|
||||||
|
|
||||||
|
if (ifa->wait_timer)
|
||||||
|
tm_stop(ifa->wait_timer);
|
||||||
|
|
||||||
if (ifa->type == OSPF_IT_VLINK)
|
if (ifa->type == OSPF_IT_VLINK)
|
||||||
{
|
{
|
||||||
ifa->vifa = NULL;
|
ifa->vifa = NULL;
|
||||||
|
@ -262,18 +202,70 @@ ospf_iface_down(struct ospf_iface *ifa)
|
||||||
ifa->sk = NULL;
|
ifa->sk = NULL;
|
||||||
ifa->cost = 0;
|
ifa->cost = 0;
|
||||||
ifa->vip = IPA_NONE;
|
ifa->vip = IPA_NONE;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{
|
|
||||||
ospf_sk_close(ifa);
|
|
||||||
rfree(ifa->wait_timer);
|
static void
|
||||||
rfree(ifa->hello_timer);
|
ospf_iface_remove(struct ospf_iface *ifa)
|
||||||
rfree(ifa->poll_timer);
|
{
|
||||||
rfree(ifa->lock);
|
ospf_iface_sm(ifa, ISM_DOWN);
|
||||||
rem_node(NODE ifa);
|
rem_node(NODE ifa);
|
||||||
mb_free(ifa);
|
rfree(ifa->pool);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ospf_iface_chstate - handle changes of interface state
|
||||||
|
* @ifa: OSPF interface
|
||||||
|
* @state: new state
|
||||||
|
*
|
||||||
|
* Many actions must be taken according to interface state changes. New network
|
||||||
|
* LSAs must be originated, flushed, new multicast sockets to listen for messages for
|
||||||
|
* %ALLDROUTERS have to be opened, etc.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
ospf_iface_chstate(struct ospf_iface *ifa, u8 state)
|
||||||
|
{
|
||||||
|
struct proto_ospf *po = ifa->oa->po;
|
||||||
|
struct proto *p = &po->proto;
|
||||||
|
u8 oldstate = ifa->state;
|
||||||
|
|
||||||
|
if (oldstate == state)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ifa->state = state;
|
||||||
|
|
||||||
|
if (ifa->type == OSPF_IT_VLINK)
|
||||||
|
OSPF_TRACE(D_EVENTS, "Changing state of virtual link %R from %s to %s",
|
||||||
|
ifa->vid, ospf_is[oldstate], ospf_is[state]);
|
||||||
|
else
|
||||||
|
OSPF_TRACE(D_EVENTS, "Changing state of iface %s from %s to %s",
|
||||||
|
ifa->iface->name, ospf_is[oldstate], ospf_is[state]);
|
||||||
|
|
||||||
|
if (ifa->type == OSPF_IT_BCAST)
|
||||||
|
{
|
||||||
|
if ((state == OSPF_IS_BACKUP) || (state == OSPF_IS_DR))
|
||||||
|
ospf_sk_join_dr(ifa);
|
||||||
|
else
|
||||||
|
ospf_sk_leave_dr(ifa);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((oldstate == OSPF_IS_DR) && (ifa->net_lsa != NULL))
|
||||||
|
{
|
||||||
|
ifa->net_lsa->lsa.age = LSA_MAXAGE;
|
||||||
|
if (state >= OSPF_IS_WAITING)
|
||||||
|
ospf_lsupd_flush_nlsa(po, ifa->net_lsa);
|
||||||
|
|
||||||
|
if (can_flush_lsa(po))
|
||||||
|
flush_lsa(ifa->net_lsa, po);
|
||||||
|
ifa->net_lsa = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((oldstate > OSPF_IS_LOOP) && (state <= OSPF_IS_LOOP))
|
||||||
|
ospf_iface_down(ifa);
|
||||||
|
|
||||||
|
schedule_rt_lsa(ifa->oa);
|
||||||
|
// FIXME flushling of link LSA
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -281,21 +273,22 @@ ospf_iface_down(struct ospf_iface *ifa)
|
||||||
* @ifa: OSPF interface
|
* @ifa: OSPF interface
|
||||||
* @event: event comming to state machine
|
* @event: event comming to state machine
|
||||||
*
|
*
|
||||||
* This fully respects 9.3 of RFC 2328 except we don't use %LOOP state of
|
* This fully respects 9.3 of RFC 2328 except we have slightly
|
||||||
* interface.
|
* different handling of %DOWN and %LOOP state. We remove intefaces
|
||||||
|
* that are %DOWN. %DOWN state is used when an interface is waiting
|
||||||
|
* for a lock. %LOOP state is used when an interface does not have a
|
||||||
|
* link.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
ospf_iface_sm(struct ospf_iface *ifa, int event)
|
ospf_iface_sm(struct ospf_iface *ifa, int event)
|
||||||
{
|
{
|
||||||
struct ospf_area *oa = ifa->oa;
|
|
||||||
|
|
||||||
DBG("SM on %s %s. Event is '%s'\n", (ifa->type == OSPF_IT_VLINK) ? "vlink" : "iface",
|
DBG("SM on %s %s. Event is '%s'\n", (ifa->type == OSPF_IT_VLINK) ? "vlink" : "iface",
|
||||||
ifa->iface ? ifa->iface->name : "(none)" , ospf_ism[event]);
|
ifa->iface ? ifa->iface->name : "(none)" , ospf_ism[event]);
|
||||||
|
|
||||||
switch (event)
|
switch (event)
|
||||||
{
|
{
|
||||||
case ISM_UP:
|
case ISM_UP:
|
||||||
if (ifa->state == OSPF_IS_DOWN)
|
if (ifa->state <= OSPF_IS_LOOP)
|
||||||
{
|
{
|
||||||
/* Now, nothing should be adjacent */
|
/* Now, nothing should be adjacent */
|
||||||
if ((ifa->type == OSPF_IT_PTP) || (ifa->type == OSPF_IT_VLINK))
|
if ((ifa->type == OSPF_IT_PTP) || (ifa->type == OSPF_IT_VLINK))
|
||||||
|
@ -319,10 +312,10 @@ ospf_iface_sm(struct ospf_iface *ifa, int event)
|
||||||
tm_start(ifa->poll_timer, ifa->pollint);
|
tm_start(ifa->poll_timer, ifa->pollint);
|
||||||
|
|
||||||
hello_timer_hook(ifa->hello_timer);
|
hello_timer_hook(ifa->hello_timer);
|
||||||
}
|
|
||||||
schedule_link_lsa(ifa);
|
schedule_link_lsa(ifa);
|
||||||
schedule_rt_lsa(ifa->oa);
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ISM_BACKS:
|
case ISM_BACKS:
|
||||||
case ISM_WAITF:
|
case ISM_WAITF:
|
||||||
if (ifa->state == OSPF_IS_WAITING)
|
if (ifa->state == OSPF_IS_WAITING)
|
||||||
|
@ -330,6 +323,7 @@ ospf_iface_sm(struct ospf_iface *ifa, int event)
|
||||||
bdr_election(ifa);
|
bdr_election(ifa);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ISM_NEICH:
|
case ISM_NEICH:
|
||||||
if ((ifa->state == OSPF_IS_DROTHER) || (ifa->state == OSPF_IS_DR) ||
|
if ((ifa->state == OSPF_IS_DROTHER) || (ifa->state == OSPF_IS_DR) ||
|
||||||
(ifa->state == OSPF_IS_BACKUP))
|
(ifa->state == OSPF_IS_BACKUP))
|
||||||
|
@ -338,19 +332,22 @@ ospf_iface_sm(struct ospf_iface *ifa, int event)
|
||||||
schedule_rt_lsa(ifa->oa);
|
schedule_rt_lsa(ifa->oa);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ISM_DOWN:
|
|
||||||
ospf_iface_chstate(ifa, OSPF_IS_DOWN);
|
|
||||||
ospf_iface_down(ifa);
|
|
||||||
schedule_rt_lsa(oa);
|
|
||||||
break;
|
|
||||||
/*
|
|
||||||
case ISM_LOOP:
|
case ISM_LOOP:
|
||||||
|
if (ifa->sk && ifa->use_link)
|
||||||
ospf_iface_chstate(ifa, OSPF_IS_LOOP);
|
ospf_iface_chstate(ifa, OSPF_IS_LOOP);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ISM_UNLOOP:
|
case ISM_UNLOOP:
|
||||||
|
/* Immediate go UP */
|
||||||
|
if (ifa->state == OSPF_IS_LOOP)
|
||||||
|
ospf_iface_sm(ifa, ISM_UP);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ISM_DOWN:
|
||||||
ospf_iface_chstate(ifa, OSPF_IS_DOWN);
|
ospf_iface_chstate(ifa, OSPF_IS_DOWN);
|
||||||
break;
|
break;
|
||||||
*/
|
|
||||||
default:
|
default:
|
||||||
bug("OSPF_I_SM - Unknown event?");
|
bug("OSPF_I_SM - Unknown event?");
|
||||||
break;
|
break;
|
||||||
|
@ -391,8 +388,6 @@ ospf_iface_add(struct object_lock *lock)
|
||||||
struct proto_ospf *po = ifa->oa->po;
|
struct proto_ospf *po = ifa->oa->po;
|
||||||
struct proto *p = &po->proto;
|
struct proto *p = &po->proto;
|
||||||
|
|
||||||
ifa->lock = lock;
|
|
||||||
|
|
||||||
if (ospf_sk_open(ifa))
|
if (ospf_sk_open(ifa))
|
||||||
{
|
{
|
||||||
if (ifa->type != OSPF_IT_NBMA)
|
if (ifa->type != OSPF_IT_NBMA)
|
||||||
|
@ -405,8 +400,8 @@ ospf_iface_add(struct object_lock *lock)
|
||||||
ifa->stub = 1;
|
ifa->stub = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ifa->state = OSPF_IS_DOWN;
|
/* Do iface UP, unless there is no link and we use link detection */
|
||||||
ospf_iface_sm(ifa, ISM_UP);
|
ospf_iface_sm(ifa, (ifa->use_link && !(ifa->iface->flags & IF_LINK_UP)) ? ISM_LOOP : ISM_UP);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -414,6 +409,7 @@ ospf_iface_new(struct proto_ospf *po, struct iface *iface, struct ifa *addr,
|
||||||
struct ospf_area_config *ac, struct ospf_iface_patt *ip)
|
struct ospf_area_config *ac, struct ospf_iface_patt *ip)
|
||||||
{
|
{
|
||||||
struct proto *p = &po->proto;
|
struct proto *p = &po->proto;
|
||||||
|
struct pool *pool = rp_new(p->pool, "OSPF Interface");
|
||||||
struct ospf_iface *ifa;
|
struct ospf_iface *ifa;
|
||||||
struct nbma_node *nbma, *nb;
|
struct nbma_node *nbma, *nb;
|
||||||
struct object_lock *lock;
|
struct object_lock *lock;
|
||||||
|
@ -422,9 +418,10 @@ ospf_iface_new(struct proto_ospf *po, struct iface *iface, struct ifa *addr,
|
||||||
if (ip->type != OSPF_IT_VLINK)
|
if (ip->type != OSPF_IT_VLINK)
|
||||||
OSPF_TRACE(D_EVENTS, "Adding interface %s", iface->name);
|
OSPF_TRACE(D_EVENTS, "Adding interface %s", iface->name);
|
||||||
|
|
||||||
ifa = mb_allocz(p->pool, sizeof(struct ospf_iface));
|
ifa = mb_allocz(pool, sizeof(struct ospf_iface));
|
||||||
ifa->iface = iface;
|
ifa->iface = iface;
|
||||||
ifa->addr = addr;
|
ifa->addr = addr;
|
||||||
|
ifa->pool = pool;
|
||||||
|
|
||||||
ifa->cost = ip->cost;
|
ifa->cost = ip->cost;
|
||||||
ifa->rxmtint = ip->rxmtint;
|
ifa->rxmtint = ip->rxmtint;
|
||||||
|
@ -438,6 +435,7 @@ ospf_iface_new(struct proto_ospf *po, struct iface *iface, struct ifa *addr,
|
||||||
ifa->stub = ospf_iface_stubby(ip, addr);
|
ifa->stub = ospf_iface_stubby(ip, addr);
|
||||||
ifa->ioprob = OSPF_I_OK;
|
ifa->ioprob = OSPF_I_OK;
|
||||||
ifa->rxbuf = ip->rxbuf;
|
ifa->rxbuf = ip->rxbuf;
|
||||||
|
ifa->use_link = ip->use_link;
|
||||||
|
|
||||||
#ifdef OSPFv2
|
#ifdef OSPFv2
|
||||||
ifa->autype = ip->autype;
|
ifa->autype = ip->autype;
|
||||||
|
@ -475,40 +473,41 @@ ospf_iface_new(struct proto_ospf *po, struct iface *iface, struct ifa *addr,
|
||||||
if (!ipa_in_net(nb->ip, addr->prefix, addr->pxlen))
|
if (!ipa_in_net(nb->ip, addr->prefix, addr->pxlen))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
nbma = mb_alloc(p->pool, sizeof(struct nbma_node));
|
nbma = mb_alloc(pool, sizeof(struct nbma_node));
|
||||||
nbma->ip = nb->ip;
|
nbma->ip = nb->ip;
|
||||||
nbma->eligible = nb->eligible;
|
nbma->eligible = nb->eligible;
|
||||||
add_tail(&ifa->nbma_list, NODE nbma);
|
add_tail(&ifa->nbma_list, NODE nbma);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add hello timer */
|
DBG("%s: Installing hello timer. (%u)\n", p->name, ifa->helloint);
|
||||||
ifa->hello_timer = tm_new(p->pool);
|
ifa->hello_timer = tm_new(pool);
|
||||||
ifa->hello_timer->data = ifa;
|
ifa->hello_timer->data = ifa;
|
||||||
ifa->hello_timer->randomize = 0;
|
ifa->hello_timer->randomize = 0;
|
||||||
ifa->hello_timer->hook = hello_timer_hook;
|
ifa->hello_timer->hook = hello_timer_hook;
|
||||||
ifa->hello_timer->recurrent = ifa->helloint;
|
ifa->hello_timer->recurrent = ifa->helloint;
|
||||||
DBG("%s: Installing hello timer. (%u)\n", p->name, ifa->helloint);
|
|
||||||
|
|
||||||
if (ifa->type == OSPF_IT_NBMA)
|
if (ifa->type == OSPF_IT_NBMA)
|
||||||
{
|
{
|
||||||
ifa->poll_timer = tm_new(p->pool);
|
DBG("%s: Installing poll timer. (%u)\n", p->name, ifa->pollint);
|
||||||
|
ifa->poll_timer = tm_new(pool);
|
||||||
ifa->poll_timer->data = ifa;
|
ifa->poll_timer->data = ifa;
|
||||||
ifa->poll_timer->randomize = 0;
|
ifa->poll_timer->randomize = 0;
|
||||||
ifa->poll_timer->hook = poll_timer_hook;
|
ifa->poll_timer->hook = poll_timer_hook;
|
||||||
ifa->poll_timer->recurrent = ifa->pollint;
|
ifa->poll_timer->recurrent = ifa->pollint;
|
||||||
DBG("%s: Installing poll timer. (%u)\n", p->name, ifa->pollint);
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
ifa->poll_timer = NULL;
|
|
||||||
|
|
||||||
ifa->wait_timer = tm_new(p->pool);
|
if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_NBMA))
|
||||||
|
{
|
||||||
|
DBG("%s: Installing wait timer. (%u)\n", p->name, ifa->waitint);
|
||||||
|
ifa->wait_timer = tm_new(pool);
|
||||||
ifa->wait_timer->data = ifa;
|
ifa->wait_timer->data = ifa;
|
||||||
ifa->wait_timer->randomize = 0;
|
ifa->wait_timer->randomize = 0;
|
||||||
ifa->wait_timer->hook = wait_timer_hook;
|
ifa->wait_timer->hook = wait_timer_hook;
|
||||||
ifa->wait_timer->recurrent = 0;
|
ifa->wait_timer->recurrent = 0;
|
||||||
DBG("%s: Installing wait timer. (%u)\n", p->name, ifa->waitint);
|
}
|
||||||
add_tail(&((struct proto_ospf *) p)->iface_list, NODE ifa);
|
|
||||||
ifa->state = OSPF_IS_DOWN;
|
ifa->state = OSPF_IS_DOWN;
|
||||||
|
add_tail(&po->iface_list, NODE ifa);
|
||||||
|
|
||||||
ifa->oa = NULL;
|
ifa->oa = NULL;
|
||||||
WALK_LIST(oa, po->area_list)
|
WALK_LIST(oa, po->area_list)
|
||||||
|
@ -539,7 +538,7 @@ ospf_iface_new(struct proto_ospf *po, struct iface *iface, struct ifa *addr,
|
||||||
* Therefore, we store such info to lock->addr field.
|
* Therefore, we store such info to lock->addr field.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
lock = olock_new(p->pool);
|
lock = olock_new(pool);
|
||||||
#ifdef OSPFv2
|
#ifdef OSPFv2
|
||||||
lock->addr = ifa->addr->prefix;
|
lock->addr = ifa->addr->prefix;
|
||||||
#else /* OSPFv3 */
|
#else /* OSPFv3 */
|
||||||
|
@ -597,7 +596,7 @@ ospf_ifa_notify(struct proto *p, unsigned flags, struct ifa *a)
|
||||||
WALK_LIST_DELSAFE(ifa, ifx, po->iface_list)
|
WALK_LIST_DELSAFE(ifa, ifx, po->iface_list)
|
||||||
{
|
{
|
||||||
if ((ifa->type != OSPF_IT_VLINK) && (ifa->addr == a))
|
if ((ifa->type != OSPF_IT_VLINK) && (ifa->addr == a))
|
||||||
ospf_iface_sm(ifa, ISM_DOWN);
|
ospf_iface_remove(ifa);
|
||||||
/* See a note in ospf_iface_notify() */
|
/* See a note in ospf_iface_notify() */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -675,7 +674,7 @@ ospf_ifa_notify(struct proto *p, unsigned flags, struct ifa *a)
|
||||||
WALK_LIST_DELSAFE(ifa, ifx, po->iface_list)
|
WALK_LIST_DELSAFE(ifa, ifx, po->iface_list)
|
||||||
{
|
{
|
||||||
if ((ifa->type != OSPF_IT_VLINK) && (ifa->addr == a))
|
if ((ifa->type != OSPF_IT_VLINK) && (ifa->addr == a))
|
||||||
ospf_iface_sm(ifa, ISM_DOWN);
|
ospf_iface_remove(ifa);
|
||||||
/* See a note in ospf_iface_notify() */
|
/* See a note in ospf_iface_notify() */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -725,34 +724,42 @@ ospf_iface_change_mtu(struct proto_ospf *po, struct ospf_iface *ifa)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ospf_iface_notify(struct proto_ospf *po, unsigned flags, struct ospf_iface *ifa)
|
||||||
|
{
|
||||||
|
if (flags & IF_CHANGE_DOWN)
|
||||||
|
{
|
||||||
|
ospf_iface_remove(ifa);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & IF_CHANGE_LINK)
|
||||||
|
ospf_iface_sm(ifa, (ifa->iface->flags & IF_LINK_UP) ? ISM_UNLOOP : ISM_LOOP);
|
||||||
|
|
||||||
|
if (flags & IF_CHANGE_MTU)
|
||||||
|
ospf_iface_change_mtu(po, ifa);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ospf_iface_notify(struct proto *p, unsigned flags, struct iface *iface)
|
ospf_if_notify(struct proto *p, unsigned flags, struct iface *iface)
|
||||||
{
|
{
|
||||||
struct proto_ospf *po = (struct proto_ospf *) p;
|
struct proto_ospf *po = (struct proto_ospf *) p;
|
||||||
|
|
||||||
DBG("%s: If notify called\n", p->name);
|
|
||||||
if (iface->flags & IF_IGNORE)
|
if (iface->flags & IF_IGNORE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (flags & IF_CHANGE_DOWN)
|
/* Going up means that there are no such ifaces yet */
|
||||||
{
|
if (flags & IF_CHANGE_UP)
|
||||||
|
return;
|
||||||
|
|
||||||
struct ospf_iface *ifa, *ifx;
|
struct ospf_iface *ifa, *ifx;
|
||||||
WALK_LIST_DELSAFE(ifa, ifx, po->iface_list)
|
WALK_LIST_DELSAFE(ifa, ifx, po->iface_list)
|
||||||
if ((ifa->type != OSPF_IT_VLINK) && (ifa->iface == iface))
|
if ((ifa->type != OSPF_IT_VLINK) && (ifa->iface == iface))
|
||||||
ospf_iface_sm(ifa, ISM_DOWN);
|
ospf_iface_notify(po, flags, ifa);
|
||||||
|
|
||||||
/* We use here that even shutting down iface also shuts down
|
/* We use here that even shutting down iface also shuts down
|
||||||
the vlinks, but vlinks are not freed and stays in the
|
the vlinks, but vlinks are not freed and stays in the
|
||||||
iface_list even when down */
|
iface_list even when down */
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & IF_CHANGE_MTU)
|
|
||||||
{
|
|
||||||
struct ospf_iface *ifa;
|
|
||||||
WALK_LIST(ifa, po->iface_list)
|
|
||||||
if ((ifa->type != OSPF_IT_VLINK) && (ifa->iface == iface))
|
|
||||||
ospf_iface_change_mtu(po, ifa);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
void ospf_iface_chstate(struct ospf_iface *ifa, u8 state);
|
void ospf_iface_chstate(struct ospf_iface *ifa, u8 state);
|
||||||
void ospf_iface_sm(struct ospf_iface *ifa, int event);
|
void ospf_iface_sm(struct ospf_iface *ifa, int event);
|
||||||
struct ospf_iface *ospf_iface_find(struct proto_ospf *p, struct iface *what);
|
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_ifa_notify(struct proto *p, unsigned flags, struct ifa *a);
|
||||||
void ospf_iface_info(struct ospf_iface *ifa);
|
void ospf_iface_info(struct ospf_iface *ifa);
|
||||||
void ospf_iface_shutdown(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->reload_routes = ospf_reload_routes;
|
||||||
p->accept_ra_types = RA_OPTIMAL;
|
p->accept_ra_types = RA_OPTIMAL;
|
||||||
p->rt_notify = ospf_rt_notify;
|
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->ifa_notify = ospf_ifa_notify;
|
||||||
p->rte_better = ospf_rte_better;
|
p->rte_better = ospf_rte_better;
|
||||||
p->rte_same = ospf_rte_same;
|
p->rte_same = ospf_rte_same;
|
||||||
|
@ -728,7 +728,7 @@ ospf_reconfigure(struct proto *p, struct proto_config *c)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* POLL TIMER */
|
/* POLL TIMER */
|
||||||
if (oldip->pollint != newip->pollint)
|
if ((oldip->pollint != newip->pollint) && ifa->poll_timer)
|
||||||
{
|
{
|
||||||
ifa->pollint = newip->helloint;
|
ifa->pollint = newip->helloint;
|
||||||
ifa->poll_timer->recurrent = ifa->pollint;
|
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);
|
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 */
|
/* strict nbma */
|
||||||
if ((oldip->strictnbma == 0) && (newip->strictnbma != 0))
|
if ((oldip->strictnbma == 0) && (newip->strictnbma != 0))
|
||||||
{
|
{
|
||||||
|
@ -819,7 +828,7 @@ ospf_reconfigure(struct proto *p, struct proto_config *c)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* WAIT */
|
/* WAIT */
|
||||||
if (oldip->waitint != newip->waitint)
|
if ((oldip->waitint != newip->waitint) && ifa->wait_timer)
|
||||||
{
|
{
|
||||||
ifa->waitint = newip->waitint;
|
ifa->waitint = newip->waitint;
|
||||||
if (ifa->wait_timer->expires != 0)
|
if (ifa->wait_timer->expires != 0)
|
||||||
|
@ -890,7 +899,7 @@ ospf_reconfigure(struct proto *p, struct proto_config *c)
|
||||||
}
|
}
|
||||||
if (!found)
|
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->ip = nb2->ip;
|
||||||
nb1->eligible = nb2->eligible;
|
nb1->eligible = nb2->eligible;
|
||||||
add_tail(&ifa->nbma_list, NODE nb1);
|
add_tail(&ifa->nbma_list, NODE nb1);
|
||||||
|
|
|
@ -162,7 +162,7 @@ struct ospf_iface
|
||||||
struct iface *iface; /* Nest's iface */
|
struct iface *iface; /* Nest's iface */
|
||||||
struct ifa *addr; /* IP prefix associated with that OSPF iface */
|
struct ifa *addr; /* IP prefix associated with that OSPF iface */
|
||||||
struct ospf_area *oa;
|
struct ospf_area *oa;
|
||||||
struct object_lock *lock;
|
pool *pool;
|
||||||
sock *sk; /* IP socket (for DD ...) */
|
sock *sk; /* IP socket (for DD ...) */
|
||||||
list neigh_list; /* List of neigbours */
|
list neigh_list; /* List of neigbours */
|
||||||
u32 cost; /* Cost of iface */
|
u32 cost; /* Cost of iface */
|
||||||
|
@ -187,8 +187,8 @@ struct ospf_iface
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ip_addr drip; /* Designated router */
|
ip_addr drip; /* Designated router */
|
||||||
u32 drid;
|
|
||||||
ip_addr bdrip; /* Backup DR */
|
ip_addr bdrip; /* Backup DR */
|
||||||
|
u32 drid;
|
||||||
u32 bdrid;
|
u32 bdrid;
|
||||||
|
|
||||||
#ifdef OSPFv3
|
#ifdef OSPFv3
|
||||||
|
@ -207,7 +207,7 @@ struct ospf_iface
|
||||||
u8 stub; /* Inactive interface */
|
u8 stub; /* Inactive interface */
|
||||||
u8 state; /* Interface state machine */
|
u8 state; /* Interface state machine */
|
||||||
#define OSPF_IS_DOWN 0 /* Not working */
|
#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_WAITING 2 /* Waiting for Wait timer */
|
||||||
#define OSPF_IS_PTP 3 /* PTP operational */
|
#define OSPF_IS_PTP 3 /* PTP operational */
|
||||||
#define OSPF_IS_DROTHER 4 /* I'm on BCAST or NBMA and I'm not DR */
|
#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) */
|
#define OSPF_I_LL 2 /* Missing link-local address (OSPFv3) */
|
||||||
u8 sk_spf; /* Socket is a member of SPFRouters group */
|
u8 sk_spf; /* Socket is a member of SPFRouters group */
|
||||||
u8 sk_dr; /* Socket is a member of DRouters 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
|
struct ospf_md5
|
||||||
|
@ -678,8 +679,8 @@ struct ospf_neighbor
|
||||||
#define ISM_WAITF 1 /* Wait timer fired */
|
#define ISM_WAITF 1 /* Wait timer fired */
|
||||||
#define ISM_BACKS 2 /* Backup seen */
|
#define ISM_BACKS 2 /* Backup seen */
|
||||||
#define ISM_NEICH 3 /* Neighbor change */
|
#define ISM_NEICH 3 /* Neighbor change */
|
||||||
// #define ISM_LOOP 4 /* Loop indicated */
|
#define ISM_LOOP 4 /* Link down */
|
||||||
// #define ISM_UNLOOP 5 /* Unloop indicated */
|
#define ISM_UNLOOP 5 /* Link up */
|
||||||
#define ISM_DOWN 6 /* Interface down */
|
#define ISM_DOWN 6 /* Interface down */
|
||||||
|
|
||||||
/* Definitions for neighbor state machine */
|
/* Definitions for neighbor state machine */
|
||||||
|
@ -751,7 +752,8 @@ struct ospf_iface_patt
|
||||||
u32 strictnbma;
|
u32 strictnbma;
|
||||||
u32 stub;
|
u32 stub;
|
||||||
u32 vid;
|
u32 vid;
|
||||||
u32 rxbuf;
|
u16 rxbuf;
|
||||||
|
u8 use_link;
|
||||||
#define OSPF_RXBUF_NORMAL 0
|
#define OSPF_RXBUF_NORMAL 0
|
||||||
#define OSPF_RXBUF_LARGE 1
|
#define OSPF_RXBUF_LARGE 1
|
||||||
#define OSPF_RXBUF_MINSIZE 256 /* Minimal allowed size */
|
#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))
|
if ((ifa->oa != oa) || (ifa->state == OSPF_IS_DOWN))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* BIRD does not support interface loops */
|
|
||||||
ASSERT(ifa->state != OSPF_IS_LOOP);
|
|
||||||
|
|
||||||
switch (ifa->type)
|
switch (ifa->type)
|
||||||
{
|
{
|
||||||
case OSPF_IT_PTP: /* RFC2328 - 12.4.1.1 */
|
case OSPF_IT_PTP: /* RFC2328 - 12.4.1.1 */
|
||||||
|
@ -303,11 +300,24 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 *length)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ln = lsab_alloc(po, sizeof(struct ospf_lsa_rt_link));
|
ln = lsab_alloc(po, sizeof(struct ospf_lsa_rt_link));
|
||||||
|
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->type = LSART_STUB;
|
||||||
ln->id = ipa_to_u32(ifa->addr->prefix);
|
ln->id = ipa_to_u32(ifa->addr->prefix);
|
||||||
ln->data = ipa_to_u32(ipa_mkmask(ifa->addr->pxlen));
|
ln->data = ipa_to_u32(ipa_mkmask(ifa->addr->pxlen));
|
||||||
ln->metric = ifa->cost;
|
ln->metric = ifa->cost;
|
||||||
ln->padding = 0;
|
ln->padding = 0;
|
||||||
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -384,9 +394,6 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 *length)
|
||||||
if ((ifa->oa != oa) || (ifa->state == OSPF_IS_DOWN))
|
if ((ifa->oa != oa) || (ifa->state == OSPF_IS_DOWN))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* BIRD does not support interface loops */
|
|
||||||
ASSERT(ifa->state != OSPF_IS_LOOP);
|
|
||||||
|
|
||||||
/* RFC5340 - 4.4.3.2 */
|
/* RFC5340 - 4.4.3.2 */
|
||||||
switch (ifa->type)
|
switch (ifa->type)
|
||||||
{
|
{
|
||||||
|
@ -1144,6 +1151,13 @@ update_link_lsa(struct ospf_iface *ifa)
|
||||||
ifa->origlink = 0;
|
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 *
|
static void *
|
||||||
originate_prefix_rt_lsa_body(struct ospf_area *oa, u16 *length)
|
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 host_addr = 0;
|
||||||
int net_lsa;
|
int net_lsa;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
u8 flags;
|
|
||||||
|
|
||||||
ASSERT(po->lsab_used == 0);
|
ASSERT(po->lsab_used == 0);
|
||||||
lp = lsab_allocz(po, sizeof(struct ospf_lsa_prefix));
|
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))
|
configured_stubnet(oa, a))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
flags = (a->pxlen < MAX_PREFIX_LENGTH) ? 0 : OPT_PX_LA;
|
if (ifa->state == OSPF_IS_LOOP)
|
||||||
put_ipv6_prefix(lsab_alloc(po, IPV6_PREFIX_SPACE(a->pxlen)),
|
lsa_put_prefix(po, a->ip, MAX_PREFIX_LENGTH, 0);
|
||||||
a->ip, a->pxlen, flags, ifa->cost);
|
else
|
||||||
|
lsa_put_prefix(po, a->prefix, a->pxlen, ifa->cost);
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
if (flags & OPT_PX_LA)
|
if ((ifa->state == OSPF_IS_LOOP) ||
|
||||||
|
(a->pxlen == MAX_PREFIX_LENGTH))
|
||||||
host_addr = 1;
|
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. */
|
which will be used as a vlink endpoint. */
|
||||||
if (oa->ac && !EMPTY_LIST(oa->ac->vlink_list) && !host_addr && vlink_addr)
|
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)),
|
lsa_put_prefix(po, vlink_addr->ip, MAX_PREFIX_LENGTH, 0);
|
||||||
vlink_addr->ip, MAX_PREFIX_LENGTH, OPT_PX_LA, 0);
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1213,9 +1227,7 @@ originate_prefix_rt_lsa_body(struct ospf_area *oa, u16 *length)
|
||||||
WALK_LIST(sn, oa->ac->stubnet_list)
|
WALK_LIST(sn, oa->ac->stubnet_list)
|
||||||
if (!sn->hidden)
|
if (!sn->hidden)
|
||||||
{
|
{
|
||||||
flags = (sn->px.len < MAX_PREFIX_LENGTH) ? 0 : OPT_PX_LA;
|
lsa_put_prefix(po, sn->px.addr, sn->px.len, sn->cost);
|
||||||
put_ipv6_prefix(lsab_alloc(po, IPV6_PREFIX_SPACE(sn->px.len)),
|
|
||||||
sn->px.addr, sn->px.len, flags, sn->cost);
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue