Kevin C Miller <kevinm@andrew.cmu.edu>
[zebra 16681] OSPF NSSA Patches
diff --git a/lib/linklist.c b/lib/linklist.c
index 5a2b696..3cb10ca 100644
--- a/lib/linklist.c
+++ b/lib/linklist.c
@@ -162,6 +162,7 @@
{
struct listnode *node;
+ assert(list);
for (node = list->head; node; node = node->next)
{
if (node->data == val)
@@ -189,6 +190,7 @@
{
struct listnode *node;
+ assert(list);
node = list->head;
if (node)
@@ -203,6 +205,7 @@
struct listnode *node;
struct listnode *next;
+ assert(list);
for (node = list->head; node; node = next)
{
next = node->next;
@@ -221,6 +224,7 @@
struct listnode *node;
struct listnode *next;
+ assert(list);
for (node = list->head; node; node = next)
{
next = node->next;
@@ -237,6 +241,7 @@
{
listnode node;
+ assert(list);
for (node = list->head; node; nextnode (node))
if (data == getdata (node))
return node;
diff --git a/ospfd/ospf_ase.c b/ospfd/ospf_ase.c
index b60aa07..8eb7025 100644
--- a/ospfd/ospf_ase.c
+++ b/ospfd/ospf_ase.c
@@ -642,6 +642,10 @@
foreach_lsa (NSSA_LSDB (area), NULL, 0,
ospf_ase_calculate_route);
}
+ /* kevinm: And add the NSSA routes in ospf_top */
+ foreach_lsa(NSSA_LSDB (ospf_top), NULL, 0,
+ ospf_ase_calculate_route);
+
#endif /* HAVE_NSSA */
/* Compare old and new external routing table and install the
diff --git a/ospfd/ospf_flood.c b/ospfd/ospf_flood.c
index bd33c34..00a4c64 100644
--- a/ospfd/ospf_flood.c
+++ b/ospfd/ospf_flood.c
@@ -622,6 +622,7 @@
{
listnode node;
int lsa_ack_flag;
+ struct as_external_lsa *extlsa;
lsa_ack_flag = 0;
@@ -646,6 +647,7 @@
{
int continue_flag = 0;
struct ospf_area *area = getdata (node);
+ struct in_addr fwd;
listnode if_node;
switch (area->external_routing)
@@ -657,11 +659,13 @@
case OSPF_AREA_NSSA: /* Sending Type 5 or 7 into NSSA area */
#ifdef HAVE_NSSA
/* Type-7, flood NSSA area */
- if (lsa->data->type == OSPF_AS_NSSA_LSA)
+ if (lsa->data->type == OSPF_AS_NSSA_LSA &&
+ area == lsa->area) {
/* We will send it. */
continue_flag = 0;
- else
+ } else {
continue_flag = 1; /* Skip this NSSA area for Type-5's et al */
+ }
break;
#endif /* HAVE_NSSA */
diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c
index ddae980..f030027 100644
--- a/ospfd/ospf_interface.c
+++ b/ospfd/ospf_interface.c
@@ -257,7 +257,22 @@
oi->nbr_self = ospf_nbr_new (oi);
oi->nbr_self->state = NSM_TwoWay;
oi->nbr_self->priority = OSPF_IF_PARAM (oi, priority);
- oi->nbr_self->options = OSPF_OPTION_E;
+
+ switch (oi->area->external_routing)
+ {
+ case OSPF_AREA_DEFAULT:
+ SET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
+ break;
+ case OSPF_AREA_STUB:
+ UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
+ break;
+#ifdef HAVE_NSSA
+ case OSPF_AREA_NSSA:
+ UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
+ SET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
+ break;
+#endif /* HAVE_NSSA */
+ }
ospf_lsa_unlock (oi->network_lsa_self);
oi->network_lsa_self = NULL;
diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c
index a4495e9..c2fade2 100644
--- a/ospfd/ospf_lsa.c
+++ b/ospfd/ospf_lsa.c
@@ -253,6 +253,15 @@
new->retransmit_counter = 0;
new->data = ospf_lsa_data_dup (lsa->data);
+ /* kevinm: Clear the refresh_list, otherwise there are going
+ to be problems when we try to remove the LSA from the
+ queue (which it's not a member of.)
+ XXX: Should we add the LSA to the refresh_list queue? */
+ new->refresh_list = -1;
+
+ if (IS_DEBUG_OSPF (lsa, LSA))
+ zlog_info ("LSA: duplicated %p (new: %p)", lsa, new);
+
return new;
}
@@ -1420,12 +1429,14 @@
/* Get 1st IP connection for Forward Addr */
struct in_addr
-ospf_get_nssa_ip (void)
+ospf_get_nssa_ip (struct ospf_area *area)
{
struct in_addr fwd;
+ struct in_addr best_default;
listnode n1;
fwd.s_addr = 0;
+ best_default.s_addr = 0;
for (n1 = listhead (ospf_top->oiflist); n1; nextnode (n1))
@@ -1434,9 +1445,16 @@
if (if_is_operative (oi->ifp))
if (oi->area->external_routing == OSPF_AREA_NSSA)
- if (oi->address && oi->address->family == AF_INET)
- return (oi->address->u.prefix4 );
+ if (oi->address && oi->address->family == AF_INET) {
+ if (best_default.s_addr == 0) {
+ best_default = oi->address->u.prefix4;
+ }
+ if (oi->area == area)
+ return (oi->address->u.prefix4);
+ }
}
+ if (best_default.s_addr != 0)
+ return best_default;
return fwd;
}
@@ -1628,7 +1646,8 @@
ospf_install_flood_nssa (struct ospf_lsa *lsa, struct external_info *ei)
{
struct ospf_lsa *new2;
- struct as_external_lsa *extlsa;
+ struct as_external_lsa *extlsa, *newextlsa;
+ listnode node;
/* NSSA Originate or Refresh (If anyNSSA)
@@ -1645,54 +1664,61 @@
Later, ABR_TASK and P-bit will scan Type-7 LSDB and translate to
Type-5's to non-NSSA Areas. (it will also attempt a re-install) */
- /* make lsa duplicate, lock=1 */
- new2 = ospf_lsa_dup(lsa);
+ for (node = listhead (ospf_top->areas); node; nextnode (node)) {
+
+ struct ospf_area *area = getdata (node);
- /* make type-7 */
- new2->data->type = OSPF_AS_NSSA_LSA;
+ /* make lsa duplicate, lock=1 */
+ new2 = ospf_lsa_dup(lsa);
- /* set P-bit if not ABR */
- if (! OSPF_IS_ABR)
- {
- SET_FLAG(new2->data->options, OSPF_OPTION_NP);
+ /* make type-7 */
+ new2->data->type = OSPF_AS_NSSA_LSA;
- /* set non-zero FWD ADDR
+ /* set P-bit if not ABR */
+ if (! OSPF_IS_ABR)
+ {
+ SET_FLAG(new2->data->options, OSPF_OPTION_NP);
- draft-ietf-ospf-nssa-update-09.txt
+ /* set non-zero FWD ADDR
- if the network between the NSSA AS boundary router and the
- adjacent AS is advertised into OSPF as an internal OSPF route,
- the forwarding address should be the next op address as is cu
- currently done with type-5 LSAs. If the intervening network is
- not adversited into OSPF as an internal OSPF route and the
- type-7 LSA's P-bit is set a forwarding address should be
- selected from one of the router's active OSPF inteface addresses
- which belong to the NSSA. If no such addresses exist, then
- no type-7 LSA's with the P-bit set should originate from this
- router. */
+ draft-ietf-ospf-nssa-update-09.txt
- extlsa = (struct as_external_lsa *)(lsa->data);
+ if the network between the NSSA AS boundary router and the
+ adjacent AS is advertised into OSPF as an internal OSPF route,
+ the forwarding address should be the next op address as is cu
+ currently done with type-5 LSAs. If the intervening network is
+ not adversited into OSPF as an internal OSPF route and the
+ type-7 LSA's P-bit is set a forwarding address should be
+ selected from one of the router's active OSPF inteface addresses
+ which belong to the NSSA. If no such addresses exist, then
+ no type-7 LSA's with the P-bit set should originate from this
+ router. */
- if (extlsa->e[0].fwd_addr.s_addr == 0)
- extlsa->e[0].fwd_addr = ospf_get_nssa_ip(); /* this NSSA area in ifp */
+ /* not updating lsa anymore, just new2 */
+ extlsa = (struct as_external_lsa *)(new2->data);
- if (IS_DEBUG_OSPF_NSSA)
- if (extlsa->e[0].fwd_addr.s_addr == 0)
- {
- zlog_info ("LSA[Type-7]: Could not build FWD-ADDR");
- ospf_lsa_discard(new2);
- return;
- }
- }
+ if (extlsa->e[0].fwd_addr.s_addr == 0)
+ /* this NSSA area in ifp */
+ extlsa->e[0].fwd_addr = ospf_get_nssa_ip(area);
- /* Re-calculate checksum. */
- ospf_lsa_checksum (new2->data);
+ if (IS_DEBUG_OSPF_NSSA)
+ if (extlsa->e[0].fwd_addr.s_addr == 0)
+ {
+ zlog_info ("LSA[Type-7]: Could not build FWD-ADDR");
+ ospf_lsa_discard(new2);
+ return;
+ }
+ }
- /* install also as Type-7 */
- ospf_lsa_install (NULL, new2); /* Remove Old, Lock New = 2 */
+ /* Re-calculate checksum. */
+ ospf_lsa_checksum (new2->data);
- /* will send each copy, lock=2+n */
- ospf_flood_through_as (NULL, new2); /* all attached NSSA's, no AS/STUBs */
+ /* install also as Type-7 */
+ ospf_lsa_install (NULL, new2); /* Remove Old, Lock New = 2 */
+
+ /* will send each copy, lock=2+n */
+ ospf_flood_through_as (NULL, new2); /* all attached NSSA's, no AS/STUBs */
+ }
/* last send, lock=2 LSA is now permanent in Type-7 LSDB */
/* It has the same ID as it's Type-5 Counter-Part */
@@ -2257,6 +2283,13 @@
/* Set LSDB. */
switch (lsa->data->type)
{
+ /* kevinm */
+ case OSPF_AS_NSSA_LSA:
+ if (lsa->area)
+ lsdb = lsa->area->lsdb;
+ else
+ lsdb = ospf_top->lsdb;
+ break;
case OSPF_AS_EXTERNAL_LSA:
#ifdef HAVE_OPAQUE_LSA
case OSPF_OPAQUE_AS_LSA:
@@ -2370,6 +2403,9 @@
#ifdef HAVE_OPAQUE_LSA
case OSPF_OPAQUE_AS_LSA:
#endif /* HAVE_OPAQUE_LSA */
+#ifdef HAVE_NSSA
+ case OSPF_AS_NSSA_LSA:
+#endif
zlog_info ("LSA[%s]: Install %s",
dump_lsa_key (new),
LOOKUP (ospf_lsa_type_msg, new->data->type));
@@ -2579,6 +2615,9 @@
#ifdef HAVE_OPAQUE_LSA
case OSPF_OPAQUE_AS_LSA:
#endif /* HAVE_OPAQUE_LSA */
+#ifdef HAVE_NSSA
+ case OSPF_AS_NSSA_LSA:
+#endif
ospf_ase_incremental_update (lsa, ospf_top);
break;
default:
@@ -3260,6 +3299,8 @@
top->lsa_refresh_queue.qs[index] = list_new ();
listnode_add (top->lsa_refresh_queue.qs[index], ospf_lsa_lock (lsa));
lsa->refresh_list = index;
+ if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
+ zlog_info ("LSA[Refresh]: ospf_refresher_register_lsa(): setting refresh_list on lsa %p (slod %d)", lsa, index);
}
}
@@ -3324,7 +3365,7 @@
next = node->next;
if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
- zlog_info ("LSA[Refresh]: ospf_lsa_refresh_walker(): refresh lsa %p", lsa);
+ zlog_info ("LSA[Refresh]: ospf_lsa_refresh_walker(): refresh lsa %p (slot %d)", lsa, i);
list_delete_node (refresh_list, node);
ospf_lsa_unlock (lsa);
diff --git a/ospfd/ospf_lsa.h b/ospfd/ospf_lsa.h
index 02fbe70..4303bcd 100644
--- a/ospfd/ospf_lsa.h
+++ b/ospfd/ospf_lsa.h
@@ -323,4 +323,8 @@
int metric_type (u_char);
int metric_value (u_char);
+#ifdef HAVE_NSSA
+struct in_addr ospf_get_nssa_ip (struct ospf_area *);
+#endif
+
#endif /* _ZEBRA_OSPF_LSA_H */
diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c
index d2338ff..ceb6d84 100644
--- a/ospfd/ospf_packet.c
+++ b/ospfd/ospf_packet.c
@@ -616,16 +616,22 @@
/* increment statistics. */
oi->hello_in++;
+ zlog_info ("Packet %s [Hello:RECV]: oi hello cnt %d",
+ inet_ntoa (ospfh->router_id), oi->hello_in);
hello = (struct ospf_hello *) STREAM_PNT (s);
/* If Hello is myself, silently discard. */
- if (IPV4_ADDR_SAME (&ospfh->router_id, &ospf_top->router_id))
+ if (IPV4_ADDR_SAME (&ospfh->router_id, &ospf_top->router_id)) {
+ zlog_info ("Packet %s [Hello:RECV]: router_id matches our router id");
return;
+ }
/* If incoming interface is passive one, ignore Hello. */
- if (OSPF_IF_PARAM (oi, passive_interface) == OSPF_IF_PASSIVE)
+ if (OSPF_IF_PARAM (oi, passive_interface) == OSPF_IF_PASSIVE) {
+ zlog_info ("Packet %s [HELLO:RECV]: oi is passive");
return;
+ }
/* get neighbor prefix. */
p.family = AF_INET;
@@ -2217,8 +2223,8 @@
/* IP Header dump. */
/*
- if (ospf_debug_packet & OSPF_DEBUG_RECV)
- ospf_ip_header_dump (ibuf);
+ if (ospf_debug_packet & OSPF_DEBUG_RECV)*/
+ ospf_ip_header_dump (ibuf); /*
*/
/* Self-originated packet should be discarded silently. */
if (ospf_if_lookup_by_local_addr (NULL, iph->ip_src))
@@ -2265,8 +2271,8 @@
}
/* Show debug receiving packet. */
- if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
- {
+ /* if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
+ {*/
if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, DETAIL))
{
zlog_info ("-----------------------------------------------------");
@@ -2281,7 +2287,7 @@
if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, DETAIL))
zlog_info ("-----------------------------------------------------");
- }
+ /* }*/
/* Some header verification. */
ret = ospf_verify_header (ibuf, oi, iph, ospfh);
@@ -2453,7 +2459,11 @@
/* Add neighbor seen. */
for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
- if ((nbr = rn->info) != NULL)
+ if ((nbr = rn->info) != NULL) {
+ zlog_info("make_hello: nbr %s, state %d",
+ inet_ntoa(nbr->router_id),
+ nbr->state);
+
/* ignore 0.0.0.0 node. */
if (nbr->router_id.s_addr != 0)
if (nbr->state != NSM_Attempt)
@@ -2466,11 +2476,12 @@
if (nbr->d_router.s_addr != 0 &&
IPV4_ADDR_SAME (&nbr->d_router, &oi->address->u.prefix4) &&
IPV4_ADDR_SAME (&nbr->bd_router, &oi->address->u.prefix4))
- flag = 1;
+ flag = 0;
stream_put_ipv4 (s, nbr->router_id.s_addr);
length += 4;
}
+ }
/* Let neighbor generate BackupSeen. */
if (flag == 1)
diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c
index 72ffe76..a8e1630 100644
--- a/ospfd/ospf_zebra.c
+++ b/ospfd/ospf_zebra.c
@@ -66,6 +66,8 @@
zlog_info ("Zebra: interface add %s index %d flags %ld metric %d mtu %d",
ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu);
+ assert(ifp->info);
+
if (!OSPF_IF_PARAM_CONFIGURED (IF_DEF_PARAMS (ifp), type))
{
SET_IF_PARAM (IF_DEF_PARAMS (ifp), type);
diff --git a/zebra/connected.c b/zebra/connected.c
index 22c9a1f..dcb0b87 100644
--- a/zebra/connected.c
+++ b/zebra/connected.c
@@ -69,7 +69,7 @@
p.prefixlen = addr->prefixlen;
/* Point-to-point check. */
- if (ifc_pointopoint (ifc))
+ if (ifc_pointopoint (ifc) && dest)
p.prefix = dest->prefix;
else
p.prefix = addr->prefix;