]> git.puffer.fish Git - mirror/frr.git/commitdiff
bgpd, zebra: Implement BGP Prefix-SID IETF draft
authorVivek Venkatraman <vivek@cumulusnetworks.com>
Thu, 9 Mar 2017 16:43:59 +0000 (11:43 -0500)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Thu, 6 Apr 2017 14:32:07 +0000 (10:32 -0400)
Implement BGP Prefix-SID IETF draft to be able to signal a labeled-unicast
prefix with a label index (segment ID). This makes it easier to deploy
global MPLS labels with BGP, even without other aspects of Segment Routing
implemented.

This patch implements configuration of the global label block (SRGB) and
configuration of a label-index for a network in BGP.

Signed-off-by: Vivek Venkatraman <vivek@cumulusnetworks.com>
bgpd/bgp_route.c
bgpd/bgp_route.h
zebra/zebra_mpls.c
zebra/zebra_mpls.h
zebra/zebra_mpls_null.c
zebra/zebra_mpls_vty.c
zebra/zebra_vrf.h

index 3114893c9d0e46b5e9fa7b47ed91c3f931a07e98..0c29254f3f630b848314acfbc3b6c7c1048e167b 100644 (file)
@@ -4220,7 +4220,8 @@ bgp_static_update_safi (struct bgp *bgp, struct prefix *p,
    route should be installed as valid.  */
 static int
 bgp_static_set (struct vty *vty, const char *ip_str, 
-                afi_t afi, safi_t safi, const char *rmap, int backdoor)
+                afi_t afi, safi_t safi, const char *rmap, int backdoor,
+                u_int32_t label_index)
 {
   VTY_DECLVAR_CONTEXT(bgp, bgp);
   int ret;
@@ -4253,6 +4254,13 @@ bgp_static_set (struct vty *vty, const char *ip_str,
       /* Configuration change. */
       bgp_static = rn->info;
 
+      /* Label index cannot be changed. */
+      if (bgp_static->label_index != label_index)
+        {
+          vty_out (vty, "%% Label index cannot be changed%s", VTY_NEWLINE);
+          return CMD_WARNING;
+        }
+
       /* Check previous routes are installed into BGP.  */
       if (bgp_static->valid && bgp_static->backdoor != backdoor)
         need_update = 1;
@@ -4284,6 +4292,7 @@ bgp_static_set (struct vty *vty, const char *ip_str,
       bgp_static->valid = 0;
       bgp_static->igpmetric = 0;
       bgp_static->igpnexthop.s_addr = 0;
+      bgp_static->label_index = label_index;
       
       if (rmap)
        {
@@ -4810,7 +4819,8 @@ DEFUN (bgp_network,
 {
   int idx_ipv4_prefixlen = 1;
   return bgp_static_set (vty, argv[idx_ipv4_prefixlen]->arg,
-                        AFI_IP, bgp_node_safi (vty), NULL, 0);
+                        AFI_IP, bgp_node_safi (vty), NULL, 0,
+                         BGP_INVALID_LABEL_INDEX);
 }
 
 DEFUN (bgp_network_route_map,
@@ -4824,7 +4834,8 @@ DEFUN (bgp_network_route_map,
   int idx_ipv4_prefixlen = 1;
   int idx_word = 3;
   return bgp_static_set (vty, argv[idx_ipv4_prefixlen]->arg,
-                        AFI_IP, bgp_node_safi (vty), argv[idx_word]->arg, 0);
+                        AFI_IP, bgp_node_safi (vty), argv[idx_word]->arg, 0,
+                         BGP_INVALID_LABEL_INDEX);
 }
 
 DEFUN (bgp_network_backdoor,
@@ -4836,7 +4847,7 @@ DEFUN (bgp_network_backdoor,
 {
   int idx_ipv4_prefixlen = 1;
   return bgp_static_set (vty, argv[idx_ipv4_prefixlen]->arg, AFI_IP, SAFI_UNICAST,
-                         NULL, 1);
+                         NULL, 1, BGP_INVALID_LABEL_INDEX);
 }
 
 DEFUN (bgp_network_mask,
@@ -4860,7 +4871,7 @@ DEFUN (bgp_network_mask,
     }
 
   return bgp_static_set (vty, prefix_str,
-                        AFI_IP, bgp_node_safi (vty), NULL, 0);
+                        AFI_IP, bgp_node_safi (vty), NULL, 0, BGP_INVALID_LABEL_INDEX);
 }
 
 DEFUN (bgp_network_mask_route_map,
@@ -4887,7 +4898,7 @@ DEFUN (bgp_network_mask_route_map,
     }
 
   return bgp_static_set (vty, prefix_str,
-                        AFI_IP, bgp_node_safi (vty), argv[idx_word]->arg, 0);
+                        AFI_IP, bgp_node_safi (vty), argv[idx_word]->arg, 0, BGP_INVALID_LABEL_INDEX);
 }
 
 DEFUN (bgp_network_mask_backdoor,
@@ -4912,7 +4923,8 @@ DEFUN (bgp_network_mask_backdoor,
     }
 
   return bgp_static_set (vty, prefix_str, AFI_IP, SAFI_UNICAST,
-                         NULL, 1);
+                         NULL, 1,
+                         BGP_INVALID_LABEL_INDEX);
 }
 
 DEFUN (bgp_network_mask_natural,
@@ -4933,7 +4945,8 @@ DEFUN (bgp_network_mask_natural,
     }
 
   return bgp_static_set (vty, prefix_str,
-                        AFI_IP, bgp_node_safi (vty), NULL, 0);
+                        AFI_IP, bgp_node_safi (vty), NULL, 0,
+                         BGP_INVALID_LABEL_INDEX);
 }
 
 DEFUN (bgp_network_mask_natural_route_map,
@@ -4957,7 +4970,8 @@ DEFUN (bgp_network_mask_natural_route_map,
     }
 
   return bgp_static_set (vty, prefix_str,
-                        AFI_IP, bgp_node_safi (vty), argv[idx_word]->arg, 0);
+                        AFI_IP, bgp_node_safi (vty), argv[idx_word]->arg, 0,
+                         BGP_INVALID_LABEL_INDEX);
 }
 
 DEFUN (bgp_network_mask_natural_backdoor,
@@ -4979,7 +4993,39 @@ DEFUN (bgp_network_mask_natural_backdoor,
     }
 
   return bgp_static_set (vty, prefix_str, AFI_IP, SAFI_UNICAST,
-                         NULL, 1);
+                         NULL, 1, BGP_INVALID_LABEL_INDEX);
+}
+
+DEFUN (bgp_network_label_index,
+       bgp_network_label_index_cmd,
+       "network A.B.C.D/M label-index (0-4294967294)",
+       "Specify a network to announce via BGP\n"
+       "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
+       "Label index to associate with the prefix\n"
+       "Label index value\n")
+{
+  u_int32_t label_index;
+
+  VTY_GET_INTEGER ("label-index", label_index, argv[3]->arg);
+  return bgp_static_set (vty, argv[1]->arg,
+                         AFI_IP, bgp_node_safi (vty), NULL, 0, label_index);
+}
+
+DEFUN (bgp_network_label_index_route_map,
+       bgp_network_label_index_route_map_cmd,
+       "network A.B.C.D/M label-index (0-4294967294) route-map WORD",
+       "Specify a network to announce via BGP\n"
+       "IP prefix\n"
+       "Label index to associate with the prefix\n"
+       "Label index value\n"
+       "Route-map to modify the attributes\n"
+       "Name of the route map\n")
+{
+  u_int32_t label_index;
+
+  VTY_GET_INTEGER ("label-index", label_index, argv[3]->arg);
+  return bgp_static_set (vty, argv[1]->arg,
+                         AFI_IP, bgp_node_safi (vty), argv[5]->arg, 0, label_index);
 }
 
 DEFUN (no_bgp_network,
@@ -5050,6 +5096,26 @@ DEFUN (no_bgp_network_mask_natural,
                           bgp_node_safi (vty));
 }
 
+ALIAS (no_bgp_network,
+       no_bgp_network_label_index_cmd,
+       "no network A.B.C.D/M label-index (0-4294967294)",
+       NO_STR
+       "Specify a network to announce via BGP\n"
+       "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
+       "Label index to associate with the prefix\n"
+       "Label index value\n")
+
+ALIAS (no_bgp_network,
+       no_bgp_network_label_index_route_map_cmd,
+       "no network A.B.C.D/M label-index (0-4294967294)route-map WORD",
+       NO_STR
+       "Specify a network to announce via BGP\n"
+       "IP prefix\n"
+       "Label index to associate with the prefix\n"
+       "Label index value\n"
+       "Route-map to modify the attributes\n"
+       "Name of the route map\n")
+
 DEFUN (ipv6_bgp_network,
        ipv6_bgp_network_cmd,
        "network X:X::X:X/M",
@@ -5058,7 +5124,8 @@ DEFUN (ipv6_bgp_network,
 {
   int idx_ipv6_prefixlen = 1;
   return bgp_static_set (vty, argv[idx_ipv6_prefixlen]->arg, AFI_IP6, bgp_node_safi(vty),
-                         NULL, 0);
+                         NULL, 0,
+                         BGP_INVALID_LABEL_INDEX);
 }
 
 DEFUN (ipv6_bgp_network_route_map,
@@ -5072,7 +5139,40 @@ DEFUN (ipv6_bgp_network_route_map,
   int idx_ipv6_prefixlen = 1;
   int idx_word = 3;
   return bgp_static_set (vty, argv[idx_ipv6_prefixlen]->arg, AFI_IP6,
-                        bgp_node_safi (vty), argv[idx_word]->arg, 0);
+                        bgp_node_safi (vty), argv[idx_word]->arg, 0,
+                         BGP_INVALID_LABEL_INDEX);
+}
+
+DEFUN (ipv6_bgp_network_label_index,
+       ipv6_bgp_network_label_index_cmd,
+       "network X:X::X:X/M label-index (0-4294967294)",
+       "Specify a network to announce via BGP\n"
+       "IPv6 prefix <network>/<length>\n"
+       "Label index to associate with the prefix\n"
+       "Label index value\n")
+{
+  u_int32_t label_index;
+
+  VTY_GET_INTEGER ("label-index", label_index, argv[3]->arg);
+  return bgp_static_set (vty, argv[1]->arg,
+                         AFI_IP6, bgp_node_safi (vty), NULL, 0, label_index);
+}
+
+DEFUN (ipv6_bgp_network_label_index_route_map,
+       ipv6_bgp_network_label_index_route_map_cmd,
+       "network X:X::X:X/M label-index (0-4294967294) route-map WORD",
+       "Specify a network to announce via BGP\n"
+       "IPv6 prefix\n"
+       "Label index to associate with the prefix\n"
+       "Label index value\n"
+       "Route-map to modify the attributes\n"
+       "Name of the route map\n")
+{
+  u_int32_t label_index;
+
+  VTY_GET_INTEGER ("label-index", label_index, argv[3]->arg);
+  return bgp_static_set (vty, argv[1]->arg,
+                         AFI_IP6, bgp_node_safi (vty), argv[5]->arg, 0, label_index);
 }
 
 DEFUN (no_ipv6_bgp_network,
@@ -5088,6 +5188,26 @@ DEFUN (no_ipv6_bgp_network,
   return bgp_static_unset (vty, argv[idx_ipv6_prefixlen]->arg, AFI_IP6, bgp_node_safi(vty));
 }
 
+ALIAS (no_ipv6_bgp_network,
+       no_ipv6_bgp_network_label_index_cmd,
+       "no network X:X::X:X/M label-index (0-4294967294)",
+       NO_STR
+       "Specify a network to announce via BGP\n"
+       "IPv6 prefix <network>/<length>\n"
+       "Label index to associate with the prefix\n"
+       "Label index value\n")
+
+ALIAS (no_ipv6_bgp_network,
+       no_ipv6_bgp_network_label_index_route_map_cmd,
+       "no network X:X::X:X/M label-index (0-4294967294) route-map WORD",
+       NO_STR
+       "Specify a network to announce via BGP\n"
+       "IPv6 prefix\n"
+       "Label index to associate with the prefix\n"
+       "Label index value\n"
+       "Route-map to modify the attributes\n"
+       "Name of the route map\n")
+
 /* Aggreagete address:
 
   advertise-map  Set condition to advertise attribute
@@ -10621,6 +10741,9 @@ bgp_config_write_network (struct vty *vty, struct bgp *bgp,
                     p->prefixlen);
          }
 
+        if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
+         vty_out (vty, " label-index %u", bgp_static->label_index);
+
        if (bgp_static->rmap.name)
          vty_out (vty, " route-map %s", bgp_static->rmap.name);
        else 
@@ -10747,6 +10870,8 @@ bgp_route_init (void)
   install_element (BGP_IPV4_NODE, &bgp_network_route_map_cmd);
   install_element (BGP_IPV4_NODE, &bgp_network_mask_route_map_cmd);
   install_element (BGP_IPV4_NODE, &bgp_network_mask_natural_route_map_cmd);
+  install_element (BGP_IPV4_NODE, &no_bgp_network_label_index_cmd);
+  install_element (BGP_IPV4_NODE, &no_bgp_network_label_index_route_map_cmd);
   install_element (BGP_IPV4_NODE, &no_bgp_table_map_cmd);
   install_element (BGP_IPV4_NODE, &no_bgp_network_cmd);
   install_element (BGP_IPV4_NODE, &no_bgp_network_mask_cmd);
@@ -10782,6 +10907,8 @@ bgp_route_init (void)
   install_element (BGP_IPV4L_NODE, &bgp_network_route_map_cmd);
   install_element (BGP_IPV4L_NODE, &bgp_network_mask_route_map_cmd);
   install_element (BGP_IPV4L_NODE, &bgp_network_mask_natural_route_map_cmd);
+  install_element (BGP_IPV4L_NODE, &bgp_network_label_index_cmd);
+  install_element (BGP_IPV4L_NODE, &bgp_network_label_index_route_map_cmd);
   install_element (BGP_IPV4L_NODE, &no_bgp_table_map_cmd);
   install_element (BGP_IPV4L_NODE, &no_bgp_network_cmd);
   install_element (BGP_IPV4L_NODE, &no_bgp_network_mask_cmd);
@@ -10820,6 +10947,10 @@ bgp_route_init (void)
   install_element (BGP_IPV6_NODE, &ipv6_bgp_network_route_map_cmd);
   install_element (BGP_IPV6_NODE, &no_bgp_table_map_cmd);
   install_element (BGP_IPV6_NODE, &no_ipv6_bgp_network_cmd);
+  install_element (BGP_IPV6_NODE, &ipv6_bgp_network_label_index_cmd);
+  install_element (BGP_IPV6_NODE, &no_ipv6_bgp_network_label_index_cmd);
+  install_element (BGP_IPV6_NODE, &ipv6_bgp_network_label_index_route_map_cmd);
+  install_element (BGP_IPV6_NODE, &no_ipv6_bgp_network_label_index_route_map_cmd);
 
   install_element (BGP_IPV6_NODE, &ipv6_aggregate_address_cmd);
   install_element (BGP_IPV6_NODE, &no_ipv6_aggregate_address_cmd);
index 69b8ea8a553b42f2bf1af785986c07249871ab9a..35994d4f760d338590ba323673ff4873d4b91ffd 100644 (file)
@@ -180,6 +180,10 @@ struct bgp_static
   /* Backdoor configuration.  */
   int backdoor;
 
+  /* Label index configuration; applies to LU prefixes. */
+  u_int32_t label_index;
+#define BGP_INVALID_LABEL_INDEX   0xFFFFFFFF
+
   /* Import check status.  */
   u_char valid;
 
index f13a3f4f0a686087367d2cff1b5c924c197442c1..85ce147d25c696d5d21734350e41e50fae4f5b8a 100644 (file)
@@ -2735,6 +2735,45 @@ zebra_mpls_write_lsp_config (struct vty *vty, struct zebra_vrf *zvrf)
   return (zvrf->slsp_table->count ? 1 : 0);
 }
 
+/*
+ * Add/update global label block.
+ */
+int
+zebra_mpls_label_block_add (struct zebra_vrf *zvrf, u_int32_t start_label,
+                            u_int32_t end_label)
+{
+  zvrf->mpls_srgb.start_label = start_label;
+  zvrf->mpls_srgb.end_label = end_label;
+  return 0;
+}
+
+/*
+ * Delete global label block.
+ */
+int
+zebra_mpls_label_block_del (struct zebra_vrf *zvrf)
+{
+  zvrf->mpls_srgb.start_label = 0;
+  zvrf->mpls_srgb.end_label = 0;
+  return 0;
+}
+
+/*
+ * Display MPLS global label block configuration (VTY command handler).
+ */
+int
+zebra_mpls_write_label_block_config (struct vty *vty, struct zebra_vrf *zvrf)
+{
+  if (zvrf->mpls_srgb.start_label == 0)
+    return 0;
+
+  vty_out(vty, "mpls label global-block %u %u%s",
+          zvrf->mpls_srgb.start_label, zvrf->mpls_srgb.end_label,
+          VTY_NEWLINE);
+
+  return 1;
+}
+
 /*
  * Called upon process exiting, need to delete LSP forwarding
  * entries from the kernel.
@@ -2764,6 +2803,8 @@ zebra_mpls_init_tables (struct zebra_vrf *zvrf)
   zvrf->fec_table[AFI_IP] = route_table_init();
   zvrf->fec_table[AFI_IP6] = route_table_init();
   zvrf->mpls_flags = 0;
+  zvrf->mpls_srgb.start_label = 0;
+  zvrf->mpls_srgb.end_label = 0;
 }
 
 /*
index f9d58a46e80eab4a720b5d8d3499d05cc2c72c35..f8e95fa10025fc37b2361c94ad0584fa3adfb0f3 100644 (file)
@@ -183,6 +183,25 @@ char *
 mpls_label2str (u_int8_t num_labels, mpls_label_t *labels,
                 char *buf, int len);
 
+/*
+ * Add/update global label block.
+ */
+int
+zebra_mpls_label_block_add (struct zebra_vrf *zvrf, u_int32_t start_label,
+                            u_int32_t end_label);
+
+/*
+ * Delete global label block.
+ */
+int
+zebra_mpls_label_block_del (struct zebra_vrf *vrf);
+
+/*
+ * Display MPLS global label block configuration (VTY command handler).
+ */
+int
+zebra_mpls_write_label_block_config (struct vty *vty, struct zebra_vrf *vrf);
+
 /*
  * Install dynamic LSP entry.
  */
index d6f99b517838f82a88eb8d92d86927cd9ceca848..12176c024ef803f702e9deec20cb012b1b0f6749 100644 (file)
@@ -44,6 +44,25 @@ mpls_str2label (const char *label_str, u_int8_t *num_labels,
   return 0;
 }
 
+int
+zebra_mpls_label_block_add (struct zebra_vrf *vrf, u_int32_t start_label,
+                            u_int32_t end_label)
+{
+  return 0;
+}
+
+int
+zebra_mpls_label_block_del (struct zebra_vrf *zvrf)
+{
+  return 0;
+}
+
+int
+zebra_mpls_write_label_block_config (struct vty *vty, struct zebra_vrf *zvrf)
+{
+  return 0;
+}
+
 int
 zebra_mpls_lsp_install (struct zebra_vrf *zvrf, struct route_node *rn, struct rib *rib)
 {
index 8d8025682a509a12d0dcdae7a32fb8a0671832be..f46037487eb5dda1b9f9106855b9334d37791bdb 100644 (file)
@@ -873,6 +873,7 @@ zebra_mpls_config (struct vty *vty)
 
   write += zebra_mpls_write_lsp_config(vty, zvrf);
   write += zebra_mpls_write_fec_config(vty, zvrf);
+  write += zebra_mpls_write_label_block_config (vty, zvrf);
   return write;
 }
 
@@ -957,6 +958,85 @@ DEFUN (show_mpls_status,
   return CMD_SUCCESS;
 }
 
+static int
+zebra_mpls_global_block (struct vty *vty, int add_cmd,
+                     const char *start_label_str, const char *end_label_str)
+{
+  int ret;
+  u_int32_t start_label;
+  u_int32_t end_label;
+  struct zebra_vrf *zvrf;
+
+  zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
+  if (!zvrf)
+    {
+      vty_out (vty, "%% Default VRF does not exist%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  if (add_cmd)
+    {
+      if (!start_label_str || !end_label_str)
+        {
+          vty_out (vty, "%% Labels not specified%s", VTY_NEWLINE);
+          return CMD_WARNING;
+        }
+
+      start_label = atoi(start_label_str);
+      end_label = atoi(end_label_str);
+      if (!IS_MPLS_UNRESERVED_LABEL(start_label) ||
+          !IS_MPLS_UNRESERVED_LABEL(end_label))
+        {
+          vty_out (vty, "%% Invalid label%s", VTY_NEWLINE);
+          return CMD_WARNING;
+        }
+      if (end_label < start_label)
+        {
+          vty_out (vty, "%% End label is less than Start label%s",
+                   VTY_NEWLINE);
+          return CMD_WARNING;
+        }
+
+      ret = zebra_mpls_label_block_add (zvrf, start_label, end_label);
+    }
+  else
+    ret = zebra_mpls_label_block_del (zvrf);
+
+  if (ret)
+    {
+      vty_out (vty, "%% Global label block could not be %s%s",
+               add_cmd ? "added" : "deleted", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (mpls_label_global_block,
+       mpls_label_global_block_cmd,
+       "mpls label global-block (16-1048575) (16-1048575)",
+       MPLS_STR
+       "Label configuration\n"
+       "Configure global label block\n"
+       "Start label\n"
+       "End label\n")
+{
+  return zebra_mpls_global_block (vty, 1, argv[3]->arg, argv[4]->arg);
+}
+
+DEFUN (no_mpls_label_global_block,
+       no_mpls_label_global_block_cmd,
+       "no mpls label global-block [(16-1048575) (16-1048575)]",
+       NO_STR
+       MPLS_STR
+       "Label configuration\n"
+       "Configure global label block\n"
+       "Start label\n"
+       "End label\n")
+{
+  return zebra_mpls_global_block (vty, 0, NULL, NULL);
+}
+
 /* MPLS node for MPLS LSP. */
 static struct cmd_node mpls_node = { MPLS_NODE,  "",  1 };
 
@@ -1009,6 +1089,9 @@ zebra_mpls_vty_init (void)
   install_element (CONFIG_NODE, &mpls_label_bind_cmd);
   install_element (CONFIG_NODE, &no_mpls_label_bind_cmd);
 
+  install_element (CONFIG_NODE, &mpls_label_global_block_cmd);
+  install_element (CONFIG_NODE, &no_mpls_label_global_block_cmd);
+
   install_element (VIEW_NODE, &show_mpls_table_cmd);
   install_element (VIEW_NODE, &show_mpls_table_lsp_cmd);
   install_element (VIEW_NODE, &show_mpls_fec_cmd);
index 8333ca27d7d356e45d8d419682302d8260d9aa66..74c2a52171c54c8c470d91b34fce404322fdc545 100644 (file)
 
 #include <zebra/zebra_ns.h>
 
+/* MPLS (Segment Routing) global block */
+typedef struct mpls_srgb_t_
+{
+  u_int32_t start_label;
+  u_int32_t end_label;
+} mpls_srgb_t;
+
 /* Routing table instance.  */
 struct zebra_vrf
 {
@@ -82,6 +89,9 @@ struct zebra_vrf
   /* MPLS FEC binding table */
   struct route_table *fec_table[AFI_MAX];
 
+  /* MPLS Segment Routing Global block */
+  mpls_srgb_t mpls_srgb;
+
   /* MPLS processing flags */
   u_int16_t mpls_flags;
 #define MPLS_FLAG_SCHEDULE_LSPS    (1 << 0)