From: David Lamparter <equi...@opensourcerouting.org>

This enhancement provides some APIs to be used to set and unset MPLS
VPN static routes. The intention of this API is to be used by either vty
or zmq/capnp interface.

Signed-off-by: David Lamparter <equi...@opensourcerouting.org>
Signed-off-by: Philippe Guibert <philippe.guib...@6wind.com>
---
 bgpd/bgp_route.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 bgpd/bgpd.h      | 11 ++++++++
 2 files changed, 92 insertions(+)

diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 99637b6..7024590 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -1526,6 +1526,15 @@ bgp_process_announce_selected (struct peer *peer, struct 
bgp_info *selected,
   return 0;
 }
 
+/* API foo */
+static struct bgp_static * bgp_static_new (void);
+static void bgp_static_free (struct bgp_static *bgp_static);
+static void bgp_static_update_safi (struct bgp *bgp, struct prefix *p,
+                        struct bgp_static *bgp_static, afi_t afi, safi_t safi);
+static void bgp_static_withdraw_safi (struct bgp *bgp, struct prefix *p,
+                        afi_t afi, safi_t safi, struct prefix_rd *prd,
+                        uint32_t *labels, size_t nlabels);
+
 void bgp_vrf_clean_tables (struct bgp_vrf *vrf)
 {
   afi_t afi;
@@ -1556,6 +1565,73 @@ void bgp_vrf_clean_tables (struct bgp_vrf *vrf)
     }
 }
 
+int
+bgp_vrf_static_set (struct bgp_vrf *vrf, afi_t afi, const struct bgp_api_route 
*route)
+{
+  struct bgp_static *bgp_static;
+  struct prefix *p = (struct prefix *)&route->prefix;
+  struct bgp_node *rn;
+
+  if (afi != AFI_IP)
+    return -1;
+
+  bgp_static = bgp_static_new ();
+  bgp_static->backdoor = 0;
+  bgp_static->valid = 1;
+  bgp_static->igpmetric = 0;
+  bgp_static->igpnexthop = route->nexthop;
+  bgp_static->labels[0] = (route->label << 4) | 1;
+  bgp_static->nlabels = route->label ? 1 : 0;
+  bgp_static->prd = vrf->outbound_rd;
+  bgp_static->ecomm = vrf->rt_export;
+  if (bgp_static->ecomm)
+    {
+      assert(bgp_static->ecomm->refcnt > 0);
+      bgp_static->ecomm->refcnt++;
+    }
+
+  rn = bgp_node_get (vrf->route[afi], p);
+  if (rn->info)
+    {
+      struct bgp_static *old = rn->info;
+      if (old->ecomm)
+        ecommunity_unintern (&old->ecomm);
+      bgp_static_free (rn->info);
+      /* reference only dropped if we're replacing a route */
+      bgp_unlock_node (rn);
+    }
+  rn->info = bgp_static;
+
+  bgp_static_update_safi (vrf->bgp, p, bgp_static, afi, SAFI_MPLS_VPN);
+  return 0;
+}
+
+int
+bgp_vrf_static_unset (struct bgp_vrf *vrf, afi_t afi, const struct 
bgp_api_route *route)
+{
+  struct prefix *p = (struct prefix *)&route->prefix;
+  struct bgp_static *old;
+  struct bgp_node *rn;
+
+  if (afi != AFI_IP)
+    return -1;
+
+  rn = bgp_node_lookup (vrf->route[afi], p);
+  if (!rn || !rn->info)
+    return -1;
+
+  bgp_static_withdraw_safi (vrf->bgp, p, afi, SAFI_MPLS_VPN,
+                            &vrf->outbound_rd, NULL, 0);
+
+  old = rn->info;
+  if (old->ecomm)
+    ecommunity_unintern (&old->ecomm);
+  bgp_static_free (old);
+  rn->info = NULL;
+  bgp_unlock_node (rn);
+  return 0;
+}
+
 void
 bgp_vrf_apply_new_imports (struct bgp_vrf *vrf, afi_t afi)
 {
@@ -4013,6 +4089,10 @@ bgp_static_update_safi (struct bgp *bgp, struct prefix 
*p,
       bgp_attr_extra_get (&attr)->ecommunity = ecommunity_dup 
(bgp_static->ecomm);
       attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
     }
+
+  if (bgp_static->igpnexthop.s_addr)
+    bgp_attr_extra_get (&attr)->mp_nexthop_global_in = bgp_static->igpnexthop;
+
   /* Apply route-map. */
   if (bgp_static->rmap.name)
     {
@@ -4057,6 +4137,7 @@ bgp_static_update_safi (struct bgp *bgp, struct prefix *p,
   if (ri)
     {
       if (attrhash_cmp (ri->attr, attr_new) &&
+          labels_equal (ri, bgp_static->labels, bgp_static->nlabels) &&
           !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
         {
           bgp_unlock_node (rn);
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 7ff58ef..b3ad648 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -33,6 +33,8 @@ typedef u_int32_t as_t;
 typedef u_int16_t as16_t; /* we may still encounter 16 Bit asnums */
 typedef u_int16_t bgp_size_t;
 
+struct bgp_node;
+
 /* BGP router distinguisher value.  */
 #define BGP_RD_SIZE                8
 
@@ -225,6 +227,13 @@ struct bgp_vrf
 
 };
 
+struct bgp_api_route
+{
+  struct prefix_ipv4 prefix;
+  struct in_addr nexthop;
+  uint32_t label;
+};
+
 /* BGP peer-group support. */
 struct peer_group
 {
@@ -1041,5 +1050,7 @@ extern void bgp_vrf_delete (struct bgp_vrf *vrf);
 extern void bgp_vrf_rt_export_set (struct bgp_vrf *vrf, struct ecommunity 
*rt_export);
 extern void bgp_vrf_rt_import_set (struct bgp_vrf *vrf, struct ecommunity 
*rt_import);
 extern void bgp_vrf_clean_tables (struct bgp_vrf *vrf);
+extern int bgp_vrf_static_set (struct bgp_vrf *vrf, afi_t afi, const struct 
bgp_api_route *route);
+extern int bgp_vrf_static_unset (struct bgp_vrf *vrf, afi_t afi, const struct 
bgp_api_route *route);
 
 #endif /* _QUAGGA_BGPD_H */
-- 
2.1.4


_______________________________________________
Quagga-dev mailing list
Quagga-dev@lists.quagga.net
https://lists.quagga.net/mailman/listinfo/quagga-dev

Reply via email to