From 1b6d5c7e0873e34bb8674ed0d41795eac7a79960 Mon Sep 17 00:00:00 2001 From: Vivek Venkatraman Date: Thu, 9 Mar 2017 11:43:59 -0500 Subject: [PATCH] bgpd, zebra: Implement BGP Prefix-SID IETF draft 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 --- bgpd/bgp_route.c | 155 ++++++++++++++++++++++++++++++++++++---- bgpd/bgp_route.h | 4 ++ zebra/zebra_mpls.c | 41 +++++++++++ zebra/zebra_mpls.h | 19 +++++ zebra/zebra_mpls_null.c | 19 +++++ zebra/zebra_mpls_vty.c | 83 +++++++++++++++++++++ zebra/zebra_vrf.h | 10 +++ 7 files changed, 319 insertions(+), 12 deletions(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 3114893c9d..0c29254f3f 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -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 /, 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 /, 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 /\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 /\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); diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index 69b8ea8a55..35994d4f76 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -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; diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c index f13a3f4f0a..85ce147d25 100644 --- a/zebra/zebra_mpls.c +++ b/zebra/zebra_mpls.c @@ -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; } /* diff --git a/zebra/zebra_mpls.h b/zebra/zebra_mpls.h index f9d58a46e8..f8e95fa100 100644 --- a/zebra/zebra_mpls.h +++ b/zebra/zebra_mpls.h @@ -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. */ diff --git a/zebra/zebra_mpls_null.c b/zebra/zebra_mpls_null.c index d6f99b5178..12176c024e 100644 --- a/zebra/zebra_mpls_null.c +++ b/zebra/zebra_mpls_null.c @@ -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) { diff --git a/zebra/zebra_mpls_vty.c b/zebra/zebra_mpls_vty.c index 8d8025682a..f46037487e 100644 --- a/zebra/zebra_mpls_vty.c +++ b/zebra/zebra_mpls_vty.c @@ -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); diff --git a/zebra/zebra_vrf.h b/zebra/zebra_vrf.h index 8333ca27d7..74c2a52171 100644 --- a/zebra/zebra_vrf.h +++ b/zebra/zebra_vrf.h @@ -25,6 +25,13 @@ #include +/* 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) -- 2.39.5