[PATCH 6/9] Summary LSAs work with SADR

Dean Luga dluga93 at gmail.com
Tue Mar 7 00:56:30 CET 2017


From: dean <dluga93 at gmail.com>

Again with the same concept as for prefix LSAs, summary LSAs will
include pairs of (destination, source) prefixes instead of just
destination prefixes when SADR is enabled.

To match this change, the functions that handle the summary LSA
parsing and validation were also changed. Parsing summary LSAs is
now done using the addr_data structure, instead of prefix address
and prefix length, to avoid using a different call syntax based on
whether SADR is enabled or not.

The functions that call the summary LSA parsing function were also
changed to use the addr_data objects.
---
 proto/ospf/lsalib.c   | 27 ++++++++++++++++++++++-----
 proto/ospf/lsalib.h   |  2 +-
 proto/ospf/ospf.c     | 14 +++++++++++---
 proto/ospf/rt.c       | 35 ++++++++++++++++++++++++++---------
 proto/ospf/topology.c | 15 +++++++++++++--
 5 files changed, 73 insertions(+), 20 deletions(-)

diff --git a/proto/ospf/lsalib.c b/proto/ospf/lsalib.c
index 1bbd137..eac9780 100644
--- a/proto/ospf/lsalib.c
+++ b/proto/ospf/lsalib.c
@@ -280,13 +280,15 @@ lsa_walk_rt(struct ospf_lsa_rt_walk *rt)
 
 
 void
-lsa_parse_sum_net(struct top_hash_entry *en, int ospf2, ip_addr *ip, int *pxlen, u8 *pxopts, u32 *metric)
+lsa_parse_sum_net(struct top_hash_entry *en, int ospf2,
+    addr_data *addr,
+    u8 *pxopts, u32 *metric)
 {
   if (ospf2)
   {
     struct ospf_lsa_sum2 *ls = en->lsa_body;
-    *ip = ipa_from_u32(en->lsa.id & ls->netmask);
-    *pxlen = u32_masklen(ls->netmask);
+    *addr->prefix = ipa_from_u32(en->lsa.id & ls->netmask);
+    addr->pxlen = u32_masklen(ls->netmask);
     *pxopts = 0;
     *metric = ls->metric & LSA_METRIC_MASK;
   }
@@ -294,7 +296,12 @@ lsa_parse_sum_net(struct top_hash_entry *en, int ospf2, ip_addr *ip, int *pxlen,
   {
     struct ospf_lsa_sum3_net *ls = en->lsa_body;
     u16 rest;
-    lsa_get_ipv6_prefix(ls->prefix, ip, pxlen, pxopts, &rest);
+    u32* buf = lsa_get_ipv6_prefix(ls->prefix, addr->prefix, (int*)(&addr->pxlen), pxopts, &rest);
+
+    #ifdef SADR_OSPF
+    lsa_get_ipv6_prefix(buf, addr->src_prefix, &addr->src_pxlen, pxopts, &rest);
+    #endif
+
     *metric = ls->metric & LSA_METRIC_MASK;
   }
 }
@@ -452,12 +459,22 @@ lsa_validate_sum3_net(struct ospf_lsa_header *lsa, struct ospf_lsa_sum3_net *bod
     return 0;
 
   u8 pxl = pxlen(body->prefix);
+
+  #ifdef SADR_OSPF
+  u8 spxl = pxlen(body->prefix + IPV6_PREFIX_SPACE(pxl)/4);
+  #endif
+
   if (pxl > MAX_PREFIX_LENGTH)
     return 0;
 
   if (lsa->length != (HDRLEN + sizeof(struct ospf_lsa_sum3_net) +
-		      IPV6_PREFIX_SPACE(pxl)))
+          IPV6_PREFIX_SPACE(pxl)
+          #ifdef SADR_OSPF
+          + IPV6_PREFIX_SPACE(spxl)
+          #endif
+          )) {
     return 0;
+  }
 
   return 1;
 }
diff --git a/proto/ospf/lsalib.h b/proto/ospf/lsalib.h
index ae6af04..f306188 100644
--- a/proto/ospf/lsalib.h
+++ b/proto/ospf/lsalib.h
@@ -55,7 +55,7 @@ u16 lsa_verify_checksum(const void *lsa_n, int lsa_len);
 int lsa_comp(struct ospf_lsa_header *l1, struct ospf_lsa_header *l2);
 void lsa_walk_rt_init(struct ospf_proto *po, struct top_hash_entry *act, struct ospf_lsa_rt_walk *rt);
 int lsa_walk_rt(struct ospf_lsa_rt_walk *rt);
-void lsa_parse_sum_net(struct top_hash_entry *en, int ospf2, ip_addr *ip, int *pxlen, u8 *pxopts, u32 *metric);
+void lsa_parse_sum_net(struct top_hash_entry *en, int ospf2, addr_data *addr, u8 *pxopts, u32 *metric);
 void lsa_parse_sum_rt(struct top_hash_entry *en, int ospf2, u32 *drid, u32 *metric, u32 *options);
 void lsa_parse_ext(struct top_hash_entry *en, int ospf2, struct ospf_lsa_ext_local *rt);
 int lsa_validate(struct ospf_lsa_header *lsa, u32 lsa_type, int ospf2, void *body);
diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c
index 92545e3..1fefb8d 100644
--- a/proto/ospf/ospf.c
+++ b/proto/ospf/ospf.c
@@ -1074,13 +1074,21 @@ show_lsa_network(struct top_hash_entry *he, int ospf2)
 static inline void
 show_lsa_sum_net(struct top_hash_entry *he, int ospf2)
 {
+  addr_data addr = addr_data_init_empty();
+
   ip_addr ip;
-  int pxlen;
+  addr.prefix = &ip;
+
+  #ifdef SADR_OSPF
+  ip_addr src_ip;
+  addr.src_prefix = &src_ip;
+  #endif
+
   u8 pxopts;
   u32 metric;
 
-  lsa_parse_sum_net(he, ospf2, &ip, &pxlen, &pxopts, &metric);
-  cli_msg(-1016, "\t\txnetwork %I/%d metric %u", ip, pxlen, metric);
+  lsa_parse_sum_net(he, ospf2, &addr, &pxopts, &metric);
+  cli_msg(-1016, "\t\txnetwork %I/%d metric %u", ip, addr.pxlen, metric);
 }
 
 static inline void
diff --git a/proto/ospf/rt.c b/proto/ospf/rt.c
index fdcecae..67ea04e 100644
--- a/proto/ospf/rt.c
+++ b/proto/ospf/rt.c
@@ -763,11 +763,20 @@ ospf_rt_sum(struct ospf_area *oa)
 {
   struct ospf_proto *p = oa->po;
   struct top_hash_entry *en;
-  ip_addr ip, abrip;
+  ip_addr abrip;
   u32 dst_rid, metric, options;
   ort *abr;
-  int pxlen = -1, type = -1;
+  int type = -1;
   u8 pxopts;
+  addr_data addr = addr_data_init_empty(); // replaces ip, pxlen (and also src_ip,src_pxlen if sadr is enabled)
+
+  ip_addr a;
+  addr.prefix = &a;
+
+  #ifdef SADR_OSPF
+  ip_addr sa;
+  addr.src_prefix = &sa;
+  #endif
 
 
   OSPF_TRACE(D_EVENTS, "Starting routing table calculation for inter-area (area %R)", oa->areaid);
@@ -792,12 +801,13 @@ ospf_rt_sum(struct ospf_area *oa)
 
     if (en->lsa_type == LSA_T_SUM_NET)
     {
-      lsa_parse_sum_net(en, ospf_is_v2(p), &ip, &pxlen, &pxopts, &metric);
+      lsa_parse_sum_net(en, ospf_is_v2(p), &addr,
+        &pxopts, &metric);
 
       if (pxopts & OPT_PX_NU)
 	continue;
 
-      if (pxlen < 0 || pxlen > MAX_PREFIX_LENGTH)
+      if (addr.pxlen < 0 || addr.pxlen > MAX_PREFIX_LENGTH)
       {
 	log(L_WARN "%s: Invalid prefix in LSA (Type: %04x, Id: %R, Rt: %R)",
 	    p->p.name, en->lsa_type, en->lsa.id, en->lsa.rt);
@@ -849,7 +859,7 @@ ospf_rt_sum(struct ospf_area *oa)
     };
 
     if (type == ORT_NET)
-      ri_install_net(p, ip, pxlen, &nf);
+      ri_install_net(p, *addr.prefix, addr.pxlen, &nf);
     else
       ri_install_rt(oa, dst_rid, &nf);
   }
@@ -865,9 +875,15 @@ ospf_rt_sum_tr(struct ospf_area *oa)
   ort *re, *abr;
   ip_addr ip, abrip;
   u32 dst_rid, metric, options;
-  int pxlen;
   u8 pxopts;
 
+  addr_data addr = addr_data_init_empty();
+  addr.prefix = &ip;
+
+  #ifdef SADR_OSPF
+  ip_addr src_prefix;
+  addr.src_prefix = &src_prefix;
+  #endif
 
   if (!bb)
     return;
@@ -890,19 +906,20 @@ ospf_rt_sum_tr(struct ospf_area *oa)
 
     if (en->lsa_type == LSA_T_SUM_NET)
     {
-      lsa_parse_sum_net(en, ospf_is_v2(p), &ip, &pxlen, &pxopts, &metric);
+      lsa_parse_sum_net(en, ospf_is_v2(p), &addr,
+        &pxopts, &metric);
 
       if (pxopts & OPT_PX_NU)
 	continue;
 
-      if (pxlen < 0 || pxlen > MAX_PREFIX_LENGTH)
+      if (addr.pxlen < 0 || addr.pxlen > MAX_PREFIX_LENGTH)
       {
 	log(L_WARN "%s: Invalid prefix in LSA (Type: %04x, Id: %R, Rt: %R)",
 	    p->p.name, en->lsa_type, en->lsa.id, en->lsa.rt);
 	continue;
       }
 
-      re = fib_find(&p->rtf, &ip, pxlen);
+      re = fib_find2(&p->rtf, addr);
     }
     else // en->lsa_type == LSA_T_SUM_RT
     {
diff --git a/proto/ospf/topology.c b/proto/ospf/topology.c
index e8a3772..b1bfc48 100644
--- a/proto/ospf/topology.c
+++ b/proto/ospf/topology.c
@@ -999,9 +999,20 @@ prepare_sum3_net_lsa_body(struct ospf_proto *p, ort *nf, u32 metric)
 {
   struct ospf_lsa_sum3_net *sum;
 
-  sum = lsab_allocz(p, sizeof(struct ospf_lsa_sum3_net) + IPV6_PREFIX_SPACE(nf->fn.pxlen));
+  sum = lsab_allocz(p, sizeof(struct ospf_lsa_sum3_net) +
+    IPV6_PREFIX_SPACE(nf->fn.pxlen)
+    #ifdef SADR_OSPF
+    + IPV6_PREFIX_SPACE(nf->fn.src_pxlen)
+    #endif
+    );
   sum->metric = metric;
-  put_ipv6_prefix(sum->prefix, nf->fn.prefix, nf->fn.pxlen, 0, 0);
+  // put dst prefix
+  u32* buf = put_ipv6_prefix(sum->prefix, nf->fn.prefix, nf->fn.pxlen, 0, 0);
+
+  #ifdef SADR_OSPF
+  // put src prefix
+  put_ipv6_prefix(buf, nf->fn.src_prefix, nf->fn.src_pxlen, 0, 0);
+  #endif
 }
 
 static inline void
-- 
2.7.4



More information about the Bird-users mailing list