diff options
author | Donald Sharp <sharpd@cumulusnetworks.com> | 2017-01-26 00:26:15 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-01-26 00:26:15 +0100 |
commit | 6dfe1c38d7d4d60c3ddae3134af6877fd2047d82 (patch) | |
tree | 6c2cc885ba19231b27d346bd77230c203a8d7f54 | |
parent | Merge branch 'frr/pull/92' (BGP Large Community support) (diff) | |
parent | bgpd: restore show bgp neighbors command (diff) | |
download | frr-6dfe1c38d7d4d60c3ddae3134af6877fd2047d82.tar.xz frr-6dfe1c38d7d4d60c3ddae3134af6877fd2047d82.zip |
Merge pull request #101 from LabNConsulting/working/master/patch-set/3-vrf
Master version of basic vrf commands & some other missed fixes
-rw-r--r-- | bgpd/bgp_mplsvpn.c | 8 | ||||
-rw-r--r-- | bgpd/bgp_mplsvpn.h | 8 | ||||
-rw-r--r-- | bgpd/bgp_route.c | 2 | ||||
-rw-r--r-- | bgpd/bgp_vty.c | 4 | ||||
-rw-r--r-- | bgpd/rfapi/bgp_rfapi_cfg.c | 784 | ||||
-rw-r--r-- | bgpd/rfapi/bgp_rfapi_cfg.h | 23 | ||||
-rw-r--r-- | bgpd/rfapi/rfapi.c | 99 | ||||
-rw-r--r-- | bgpd/rfapi/rfapi_ap.c | 60 | ||||
-rw-r--r-- | bgpd/rfapi/rfapi_ap.h | 1 | ||||
-rw-r--r-- | bgpd/rfapi/rfapi_backend.h | 9 | ||||
-rw-r--r-- | bgpd/rfapi/rfapi_import.c | 17 | ||||
-rw-r--r-- | bgpd/rfapi/rfapi_import.h | 8 | ||||
-rw-r--r-- | bgpd/rfapi/rfapi_private.h | 33 | ||||
-rw-r--r-- | bgpd/rfapi/rfapi_rib.c | 24 | ||||
-rw-r--r-- | bgpd/rfapi/rfapi_rib.h | 33 | ||||
-rw-r--r-- | bgpd/rfapi/rfapi_vty.c | 663 | ||||
-rw-r--r-- | lib/command.c | 3 | ||||
-rw-r--r-- | lib/command.h | 1 | ||||
-rw-r--r-- | lib/vty.c | 1 | ||||
-rw-r--r-- | vtysh/vtysh.c | 39 |
20 files changed, 1551 insertions, 269 deletions
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index bfbddb6c3..ae0f0ab1d 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -969,7 +969,7 @@ bgp_show_mpls_vpn (struct vty *vty, afi_t afi, struct prefix_rd *prd, DEFUN (show_bgp_ip_vpn_rd, show_bgp_ip_vpn_rd_cmd, - "show [ip] bgp "BGP_AFI_CMD_STR" vpn [rd ASN:nn_or_IP-address:nn] [json]", + "show bgp "BGP_AFI_CMD_STR" vpn all [rd ASN:nn_or_IP-address:nn] [json]", SHOW_STR IP_STR BGP_STR @@ -979,7 +979,7 @@ DEFUN (show_bgp_ip_vpn_rd, "VPN Route Distinguisher\n" JSON_STR) { - int idx_ext_community = 5; + int idx_rd = 5; int ret; struct prefix_rd prd; afi_t afi; @@ -987,9 +987,9 @@ DEFUN (show_bgp_ip_vpn_rd, if (argv_find_and_parse_afi (argv, argc, &idx, &afi)) { - if (argv[idx_ext_community]->arg) + if (argc >= 7 && argv[idx_rd]->arg) { - ret = str2prefix_rd (argv[idx_ext_community]->arg, &prd); + ret = str2prefix_rd (argv[idx_rd]->arg, &prd); if (! ret) { vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE); diff --git a/bgpd/bgp_mplsvpn.h b/bgpd/bgp_mplsvpn.h index 336b73616..234cf9baa 100644 --- a/bgpd/bgp_mplsvpn.h +++ b/bgpd/bgp_mplsvpn.h @@ -30,6 +30,10 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #define RD_ADDRSTRLEN 28 +#ifdef MPLS_LABEL_MAX +# undef MPLS_LABEL_MAX +#endif + typedef enum { MPLS_LABEL_IPV4_EXPLICIT_NULL = 0, /* [RFC3032] */ MPLS_LABEL_ROUTER_ALERT = 1, /* [RFC3032] */ @@ -45,7 +49,9 @@ typedef enum { MPLS_LABEL_UNASSIGNED11 = 11, MPLS_LABEL_GAL = 13, /* [RFC5586] */ MPLS_LABEL_OAM_ALERT = 14, /* [RFC3429] */ - MPLS_LABEL_EXTENSION = 15 /* [RFC7274] */ + MPLS_LABEL_EXTENSION = 15, /* [RFC7274] */ + MPLS_LABEL_MAX = 1048575, + MPLS_LABEL_ILLEGAL = 0xFFFFFFFF /* for internal use only */ } mpls_special_label_t; #define MPLS_LABEL_IS_SPECIAL(label) \ diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 0179cc3d9..84759ca04 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -9624,7 +9624,7 @@ peer_adj_routes (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi, DEFUN (show_ip_bgp_instance_neighbor_advertised_route, show_ip_bgp_instance_neighbor_advertised_route_cmd, - "show [ip] bgp [<view|vrf> WORD] [<ipv4 [<unicast|multicast>]|ipv6 [<unicast|multicast>]|encap [unicast]|vpnv4 [unicast]>] neighbors <A.B.C.D|X:X::X:X|WORD> [<received-routes|advertised-routes> [route-map WORD]] [json]", + "show [ip] bgp [<view|vrf> WORD] [<ipv4 [<unicast|multicast>]|ipv6 [<unicast|multicast>]|encap [unicast]|vpnv4 [unicast]>] neighbors <A.B.C.D|X:X::X:X|WORD> <received-routes|advertised-routes> [route-map WORD] [json]", SHOW_STR IP_STR BGP_STR diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index e9c4a131a..17b848523 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -5609,7 +5609,6 @@ DEFUN (address_family_vpnv6, vty->node = BGP_VPNV6_NODE; return CMD_SUCCESS; } -#endif /* KEEP_OLD_VPN_COMMANDS */ DEFUN (address_family_ipv4_vpn, address_family_ipv4_vpn_cmd, @@ -5632,6 +5631,7 @@ DEFUN (address_family_ipv6_vpn, vty->node = BGP_VPNV6_NODE; return CMD_SUCCESS; } +#endif /* KEEP_OLD_VPN_COMMANDS */ DEFUN (address_family_encap, address_family_encap_cmd, @@ -10779,9 +10779,9 @@ bgp_vty_init (void) #ifdef KEEP_OLD_VPN_COMMANDS install_element (BGP_NODE, &address_family_vpnv4_cmd); install_element (BGP_NODE, &address_family_vpnv6_cmd); -#endif /* KEEP_OLD_VPN_COMMANDS */ install_element (BGP_NODE, &address_family_ipv4_vpn_cmd); install_element (BGP_NODE, &address_family_ipv6_vpn_cmd); +#endif /* KEEP_OLD_VPN_COMMANDS */ install_element (BGP_NODE, &address_family_encap_cmd); install_element (BGP_NODE, &address_family_encapv6_cmd); diff --git a/bgpd/rfapi/bgp_rfapi_cfg.c b/bgpd/rfapi/bgp_rfapi_cfg.c index ab9a24e83..10b365c1c 100644 --- a/bgpd/rfapi/bgp_rfapi_cfg.c +++ b/bgpd/rfapi/bgp_rfapi_cfg.c @@ -561,8 +561,9 @@ DEFUN (vnc_defaults_responselifetime, return CMD_SUCCESS; } -static struct rfapi_nve_group_cfg * -rfapi_group_lookup_byname (struct bgp *bgp, const char *name) +struct rfapi_nve_group_cfg * +bgp_rfapi_cfg_match_byname (struct bgp *bgp, const char *name, + rfapi_group_cfg_type_t type) /* _MAX = any */ { struct rfapi_nve_group_cfg *rfg; struct listnode *node, *nnode; @@ -570,18 +571,29 @@ rfapi_group_lookup_byname (struct bgp *bgp, const char *name) for (ALL_LIST_ELEMENTS (bgp->rfapi_cfg->nve_groups_sequential, node, nnode, rfg)) { - if (!strcmp (rfg->name, name)) + if ((type == RFAPI_GROUP_CFG_MAX || type == rfg->type) && + !strcmp (rfg->name, name)) return rfg; } return NULL; } static struct rfapi_nve_group_cfg * -rfapi_group_new () +rfapi_group_new (struct bgp *bgp, + rfapi_group_cfg_type_t type, + const char *name) { struct rfapi_nve_group_cfg *rfg; rfg = XCALLOC (MTYPE_RFAPI_GROUP_CFG, sizeof (struct rfapi_nve_group_cfg)); + if (rfg) + { + rfg->type = type; + rfg->name = strdup (name); + /* add to tail of list */ + listnode_add (bgp->rfapi_cfg->nve_groups_sequential, rfg); + } + rfg->label = MPLS_LABEL_ILLEGAL; QOBJ_REG (rfg, rfapi_nve_group_cfg); return rfg; @@ -1033,7 +1045,8 @@ DEFUN (vnc_redistribute_nvegroup, * OK if nve group doesn't exist yet; we'll set the pointer * when the group is defined later */ - bgp->rfapi_cfg->rfg_redist = rfapi_group_lookup_byname (bgp, argv[3]->arg); + bgp->rfapi_cfg->rfg_redist = bgp_rfapi_cfg_match_byname (bgp, argv[3]->arg, + RFAPI_GROUP_CFG_NVE); if (bgp->rfapi_cfg->rfg_redist_name) free (bgp->rfapi_cfg->rfg_redist_name); bgp->rfapi_cfg->rfg_redist_name = strdup (argv[3]->arg); @@ -1622,7 +1635,7 @@ DEFUN (vnc_export_nvegroup, return CMD_WARNING; } - rfg_new = rfapi_group_lookup_byname (bgp, argv[5]->arg); + rfg_new = bgp_rfapi_cfg_match_byname (bgp, argv[5]->arg, RFAPI_GROUP_CFG_NVE); if (argv[2]->arg[0] == 'b') { @@ -2417,20 +2430,17 @@ DEFUN (vnc_nve_group, struct rfapi_rfg_name *rfgn; /* Search for name */ - rfg = rfapi_group_lookup_byname (bgp, argv[2]->arg); + rfg = bgp_rfapi_cfg_match_byname (bgp, argv[2]->arg, RFAPI_GROUP_CFG_NVE); if (!rfg) { - rfg = rfapi_group_new (); + rfg = rfapi_group_new (bgp, RFAPI_GROUP_CFG_NVE, argv[2]->arg); if (!rfg) { /* Error out of memory */ vty_out (vty, "Can't allocate memory for NVE group%s", VTY_NEWLINE); return CMD_WARNING; } - rfg->name = strdup (argv[2]->arg); - /* add to tail of list */ - listnode_add (bgp->rfapi_cfg->nve_groups_sequential, rfg); /* Copy defaults from struct rfapi_cfg */ rfg->rd = bgp->rfapi_cfg->default_rd; @@ -2453,7 +2463,7 @@ DEFUN (vnc_nve_group, rfg->rt_import_list = ecommunity_dup (bgp->rfapi_cfg->default_rt_import_list); rfg->rfapi_import_table = - rfapiImportTableRefAdd (bgp, rfg->rt_import_list); + rfapiImportTableRefAdd (bgp, rfg->rt_import_list, rfg); } /* @@ -2629,7 +2639,8 @@ static int bgp_rfapi_delete_named_nve_group ( struct vty *vty, /* NULL = no output */ struct bgp *bgp, - const char *rfg_name) /* NULL = any */ + const char *rfg_name, /* NULL = any */ + rfapi_group_cfg_type_t type) /* _MAX = any */ { struct rfapi_nve_group_cfg *rfg = NULL; struct listnode *node, *nnode; @@ -2638,7 +2649,7 @@ bgp_rfapi_delete_named_nve_group ( /* Search for name */ if (rfg_name) { - rfg = rfapi_group_lookup_byname (bgp, rfg_name); + rfg = bgp_rfapi_cfg_match_byname (bgp, rfg_name, type); if (!rfg) { if (vty) @@ -2665,7 +2676,8 @@ bgp_rfapi_delete_named_nve_group ( for (ALL_LIST_ELEMENTS_RO (bgp->rfapi_cfg->rfg_export_direct_bgp_l, node, rfgn)) { - if (rfg_name == NULL || !strcmp (rfgn->name, rfg_name)) + if (rfg_name == NULL || + (type == RFAPI_GROUP_CFG_NVE && !strcmp (rfgn->name, rfg_name))) { rfgn->rfg = NULL; /* remove exported routes from this group */ @@ -2680,7 +2692,8 @@ bgp_rfapi_delete_named_nve_group ( for (ALL_LIST_ELEMENTS_RO (bgp->rfapi_cfg->rfg_export_zebra_l, node, rfgn)) { - if (rfg_name == NULL || !strcmp (rfgn->name, rfg_name)) + if (rfg_name == NULL || + (type == RFAPI_GROUP_CFG_NVE && !strcmp (rfgn->name, rfg_name))) { rfgn->rfg = NULL; /* remove exported routes from this group */ @@ -2707,7 +2720,7 @@ DEFUN (vnc_no_nve_group, { VTY_DECLVAR_CONTEXT(bgp, bgp); - return bgp_rfapi_delete_named_nve_group (vty, bgp, argv[3]->arg); + return bgp_rfapi_delete_named_nve_group (vty, bgp, argv[3]->arg, RFAPI_GROUP_CFG_NVE); } DEFUN (vnc_nve_group_prefix, @@ -2890,7 +2903,7 @@ DEFUN (vnc_nve_group_rt_import, */ if (rfg->rfapi_import_table) rfapiImportTableRefDelByIt (bgp, rfg->rfapi_import_table); - rfg->rfapi_import_table = rfapiImportTableRefAdd (bgp, rfg->rt_import_list); + rfg->rfapi_import_table = rfapiImportTableRefAdd (bgp, rfg->rt_import_list, rfg); if (is_export_bgp) vnc_direct_bgp_add_group (bgp, rfg); @@ -2997,7 +3010,7 @@ DEFUN (vnc_nve_group_rt_both, */ if (rfg->rfapi_import_table) rfapiImportTableRefDelByIt (bgp, rfg->rfapi_import_table); - rfg->rfapi_import_table = rfapiImportTableRefAdd (bgp, rfg->rt_import_list); + rfg->rfapi_import_table = rfapiImportTableRefAdd (bgp, rfg->rt_import_list, rfg); if (is_export_bgp) vnc_direct_bgp_add_group (bgp, rfg); @@ -3238,6 +3251,492 @@ static struct cmd_node bgp_vnc_nve_group_node = { }; /*------------------------------------------------------------------------- + * VNC nve-group + * Note there are two types of NVEs, one for VPNs one for RFP NVEs + *-----------------------------------------------------------------------*/ + +DEFUN (vnc_vrf_policy, + vnc_vrf_policy_cmd, + "vrf-policy NAME", + "Configure a VRF policy group\n" + "VRF name\n") +{ + struct rfapi_nve_group_cfg *rfg; + VTY_DECLVAR_CONTEXT(bgp, bgp); + + if (!bgp) + { + vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE); + return CMD_WARNING; + } + + /* Search for name */ + rfg = bgp_rfapi_cfg_match_byname (bgp, argv[1]->arg, RFAPI_GROUP_CFG_VRF); + + if (!rfg) + { + rfg = rfapi_group_new (bgp, RFAPI_GROUP_CFG_VRF, argv[1]->arg); + if (!rfg) + { + /* Error out of memory */ + vty_out (vty, "Can't allocate memory for NVE group%s", VTY_NEWLINE); + return CMD_WARNING; + } + } + /* + * XXX subsequent calls will need to make sure this item is still + * in the linked list and has the same name + */ + VTY_PUSH_CONTEXT_SUB (BGP_VRF_POLICY_NODE, rfg); + + return CMD_SUCCESS; +} + +DEFUN (vnc_no_vrf_policy, + vnc_no_vrf_policy_cmd, + "no vrf-policy NAME", + NO_STR + "Remove a VRF policy group\n" + "VRF name\n") +{ + VTY_DECLVAR_CONTEXT(bgp, bgp); + + if (!bgp) + { + vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE); + return CMD_WARNING; + } + return bgp_rfapi_delete_named_nve_group (vty, bgp, argv[2]->arg, RFAPI_GROUP_CFG_VRF); +} + +DEFUN (vnc_vrf_policy_label, + vnc_vrf_policy_label_cmd, + "label (0-1048575)", + "Default label value for VRF\n" + "Label Value <0-1048575>\n") +{ + VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); + + uint32_t label; + VTY_DECLVAR_CONTEXT(bgp, bgp); + + if (!bgp) + { + vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE); + return CMD_WARNING; + } + + /* make sure it's still in list */ + if (!listnode_lookup (bgp->rfapi_cfg->nve_groups_sequential, rfg)) + { + /* Not in list anymore */ + vty_out (vty, "Current NVE group no longer exists%s", VTY_NEWLINE); + return CMD_WARNING; + } + + VTY_GET_INTEGER_RANGE ("Label value", label, argv[1]->arg, 0, MPLS_LABEL_MAX); + + if (bgp->rfapi_cfg->rfg_redist == rfg) + { + vnc_redistribute_prechange (bgp); + } + + rfg->label = label; + + if (bgp->rfapi_cfg->rfg_redist == rfg) + { + vnc_redistribute_postchange (bgp); + } + return CMD_SUCCESS; +} + +DEFUN (vnc_vrf_policy_no_label, + vnc_vrf_policy_no_label_cmd, + "no label", + "Remove VRF default label\n") +{ + VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); + VTY_DECLVAR_CONTEXT(bgp, bgp); + + /* make sure it's still in list */ + if (!listnode_lookup (bgp->rfapi_cfg->nve_groups_sequential, rfg)) + { + /* Not in list anymore */ + vty_out (vty, "Current VRF group no longer exists%s", VTY_NEWLINE); + return CMD_WARNING; + } + + if (bgp->rfapi_cfg->rfg_redist == rfg) + { + vnc_redistribute_prechange (bgp); + } + + rfg->label = MPLS_LABEL_ILLEGAL; + + if (bgp->rfapi_cfg->rfg_redist == rfg) + { + vnc_redistribute_postchange (bgp); + } + return CMD_SUCCESS; +} + +DEFUN (vnc_vrf_policy_nexthop, + vnc_vrf_policy_nexthop_cmd, + "nexthop <A.B.C.D|X:X::X:X|self>", + "Specify next hop to use for VRF advertised prefixes\n" + "IPv4 prefix\n" + "IPv6 prefix\n" + "Use configured router-id (default)") +{ + VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); + struct prefix p; + + VTY_DECLVAR_CONTEXT(bgp, bgp); + + /* make sure it's still in list */ + if (!listnode_lookup (bgp->rfapi_cfg->nve_groups_sequential, rfg)) + { + /* Not in list anymore */ + vty_out (vty, "Current VRF no longer exists%s", VTY_NEWLINE); + return CMD_WARNING; + } + + if (bgp->rfapi_cfg->rfg_redist == rfg) + { + vnc_redistribute_prechange (bgp); + } + + if (!str2prefix (argv[1]->arg, &p) && p.family) + { + //vty_out (vty, "Nexthop set to self%s", VTY_NEWLINE); + SET_FLAG (rfg->flags, RFAPI_RFG_VPN_NH_SELF); + memset(&rfg->vn_prefix, 0, sizeof(struct prefix)); + } + else + { + UNSET_FLAG (rfg->flags, RFAPI_RFG_VPN_NH_SELF); + rfg->vn_prefix = p; + } + + /* TBD handle router-id/ nexthop changes when have advertised prefixes */ + + if (bgp->rfapi_cfg->rfg_redist == rfg) + { + vnc_redistribute_postchange (bgp); + } + + return CMD_SUCCESS; +} + +/* The RT code should be refactored/simplified with above... */ +DEFUN (vnc_vrf_policy_rt_import, + vnc_vrf_policy_rt_import_cmd, + "rt import RTLIST...", + "Specify route targets\n" + "Import filter\n" + "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n") +{ + VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); + VTY_DECLVAR_CONTEXT(bgp, bgp); + int rc; + struct listnode *node; + struct rfapi_rfg_name *rfgn; + int is_export_bgp = 0; + int is_export_zebra = 0; + + if (!bgp) + { + vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE); + return CMD_WARNING; + } + + /* make sure it's still in list */ + if (!listnode_lookup (bgp->rfapi_cfg->nve_groups_sequential, rfg)) + { + /* Not in list anymore */ + vty_out (vty, "Current NVE group no longer exists%s", VTY_NEWLINE); + return CMD_WARNING; + } + + rc = set_ecom_list (vty, argc-2, argv+2, &rfg->rt_import_list); + if (rc != CMD_SUCCESS) + return rc; + + for (ALL_LIST_ELEMENTS_RO (bgp->rfapi_cfg->rfg_export_direct_bgp_l, + node, rfgn)) + { + + if (rfgn->rfg == rfg) + { + is_export_bgp = 1; + break; + } + } + + if (is_export_bgp) + vnc_direct_bgp_del_group (bgp, rfg); + + for (ALL_LIST_ELEMENTS_RO (bgp->rfapi_cfg->rfg_export_zebra_l, node, rfgn)) + { + + if (rfgn->rfg == rfg) + { + is_export_zebra = 1; + break; + } + } + + if (is_export_zebra) + vnc_zebra_del_group (bgp, rfg); + + /* + * stop referencing old import table, now reference new one + */ + if (rfg->rfapi_import_table) + rfapiImportTableRefDelByIt (bgp, rfg->rfapi_import_table); + rfg->rfapi_import_table = rfapiImportTableRefAdd (bgp, rfg->rt_import_list, rfg); + + if (is_export_bgp) + vnc_direct_bgp_add_group (bgp, rfg); + + if (is_export_zebra) + vnc_zebra_add_group (bgp, rfg); + + return CMD_SUCCESS; +} + +DEFUN (vnc_vrf_policy_rt_export, + vnc_vrf_policy_rt_export_cmd, + "rt export RTLIST...", + "Specify route targets\n" + "Export filter\n" + "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n") +{ + VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); + VTY_DECLVAR_CONTEXT(bgp, bgp); + int rc; + + if (!bgp) + { + vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE); + return CMD_WARNING; + } + + /* make sure it's still in list */ + if (!listnode_lookup (bgp->rfapi_cfg->nve_groups_sequential, rfg)) + { + /* Not in list anymore */ + vty_out (vty, "Current NVE group no longer exists%s", VTY_NEWLINE); + return CMD_WARNING; + } + + if (bgp->rfapi_cfg->rfg_redist == rfg) + { + vnc_redistribute_prechange (bgp); + } + + rc = set_ecom_list (vty, argc-2, argv+2, &rfg->rt_export_list); + + if (bgp->rfapi_cfg->rfg_redist == rfg) + { + vnc_redistribute_postchange (bgp); + } + + return rc; +} + +DEFUN (vnc_vrf_policy_rt_both, + vnc_vrf_policy_rt_both_cmd, + "rt both RTLIST...", + "Specify route targets\n" + "Export+import filters\n" + "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n") +{ + VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); + VTY_DECLVAR_CONTEXT(bgp, bgp); + int rc; + int is_export_bgp = 0; + int is_export_zebra = 0; + struct listnode *node; + struct rfapi_rfg_name *rfgn; + + if (!bgp) + { + vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE); + return CMD_WARNING; + } + + /* make sure it's still in list */ + if (!listnode_lookup (bgp->rfapi_cfg->nve_groups_sequential, rfg)) + { + /* Not in list anymore */ + vty_out (vty, "Current NVE group no longer exists%s", VTY_NEWLINE); + return CMD_WARNING; + } + + rc = set_ecom_list (vty, argc-2, argv+2, &rfg->rt_import_list); + if (rc != CMD_SUCCESS) + return rc; + + for (ALL_LIST_ELEMENTS_RO (bgp->rfapi_cfg->rfg_export_direct_bgp_l, + node, rfgn)) + { + + if (rfgn->rfg == rfg) + { + is_export_bgp = 1; + break; + } + } + + if (is_export_bgp) + vnc_direct_bgp_del_group (bgp, rfg); + + for (ALL_LIST_ELEMENTS_RO (bgp->rfapi_cfg->rfg_export_zebra_l, node, rfgn)) + { + + if (rfgn->rfg == rfg) + { + is_export_zebra = 1; + break; + } + } + + if (is_export_zebra) + { + vnc_zlog_debug_verbose ("%s: is_export_zebra", __func__); + vnc_zebra_del_group (bgp, rfg); + } + + /* + * stop referencing old import table, now reference new one + */ + if (rfg->rfapi_import_table) + rfapiImportTableRefDelByIt (bgp, rfg->rfapi_import_table); + rfg->rfapi_import_table = rfapiImportTableRefAdd (bgp, rfg->rt_import_list, rfg); + + if (is_export_bgp) + vnc_direct_bgp_add_group (bgp, rfg); + + if (is_export_zebra) + vnc_zebra_add_group (bgp, rfg); + + if (bgp->rfapi_cfg->rfg_redist == rfg) + { + vnc_redistribute_prechange (bgp); + } + + rc = set_ecom_list (vty, argc-2, argv+2, &rfg->rt_export_list); + + if (bgp->rfapi_cfg->rfg_redist == rfg) + { + vnc_redistribute_postchange (bgp); + } + + return rc; + +} + +DEFUN (vnc_vrf_policy_rd, + vnc_vrf_policy_rd_cmd, + "rd ASN:nn_or_IP-address:nn", + "Specify default VRF route distinguisher\n" + "Route Distinguisher (<as-number>:<number> | <ip-address>:<number> | auto:nh:<number> )\n") +{ + int ret; + struct prefix_rd prd; + VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); + VTY_DECLVAR_CONTEXT(bgp, bgp); + + if (!bgp) + { + vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE); + return CMD_WARNING; + } + + /* make sure it's still in list */ + if (!listnode_lookup (bgp->rfapi_cfg->nve_groups_sequential, rfg)) + { + /* Not in list anymore */ + vty_out (vty, "Current NVE group no longer exists%s", VTY_NEWLINE); + return CMD_WARNING; + } + + if (!strncmp (argv[1]->arg, "auto:nh:", 8)) + { + /* + * use AF_UNIX to designate automatically-assigned RD + * auto:vn:nn where nn is a 2-octet quantity + */ + char *end = NULL; + uint32_t value32 = strtoul (argv[1]->arg + 8, &end, 10); + uint16_t value = value32 & 0xffff; + + if (!*(argv[1]->arg + 5) || *end) + { + vty_out (vty, "%% Malformed rd%s", VTY_NEWLINE); + return CMD_WARNING; + } + if (value32 > 0xffff) + { + vty_out (vty, "%% Malformed rd (must be less than %u%s", + 0x0ffff, VTY_NEWLINE); + return CMD_WARNING; + } + + memset (&prd, 0, sizeof (prd)); + prd.family = AF_UNIX; + prd.prefixlen = 64; + prd.val[0] = (RD_TYPE_IP >> 8) & 0x0ff; + prd.val[1] = RD_TYPE_IP & 0x0ff; + prd.val[6] = (value >> 8) & 0x0ff; + prd.val[7] = value & 0x0ff; + + } + else + { + + ret = str2prefix_rd (argv[1]->arg, &prd); + if (!ret) + { + vty_out (vty, "%% Malformed rd%s", VTY_NEWLINE); + return CMD_WARNING; + } + } + + if (bgp->rfapi_cfg->rfg_redist == rfg) + { + vnc_redistribute_prechange (bgp); + } + + rfg->rd = prd; + + if (bgp->rfapi_cfg->rfg_redist == rfg) + { + vnc_redistribute_postchange (bgp); + } + return CMD_SUCCESS; +} + +DEFUN (exit_vrf_policy, + exit_vrf_policy_cmd, + "exit-vrf-policy", + "Exit VRF policy configuration mode\n") +{ + if (vty->node == BGP_VRF_POLICY_NODE) + { + vty->node = BGP_NODE; + } + return CMD_SUCCESS; +} + +static struct cmd_node bgp_vrf_policy_node = { + BGP_VRF_POLICY_NODE, + "%s(config-router-vrf-policy)# ", + 1 +}; + +/*------------------------------------------------------------------------- * vnc-l2-group *-----------------------------------------------------------------------*/ @@ -3247,11 +3746,17 @@ DEFUN (vnc_l2_group, "vnc l2-group NAME", VNC_CONFIG_STR "Configure a L2 group\n" "Group name\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); struct rfapi_l2_group_cfg *rfg; + VTY_DECLVAR_CONTEXT(bgp, bgp); + + if (!bgp) + { + vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE); + return CMD_WARNING; + } /* Search for name */ - rfg = rfapi_l2_group_lookup_byname (bgp, argv[2]->arg); + rfg = rfapi_l2_group_lookup_byname (bgp, argv[1]->arg); if (!rfg) { @@ -3262,7 +3767,7 @@ DEFUN (vnc_l2_group, vty_out (vty, "Can't allocate memory for L2 group%s", VTY_NEWLINE); return CMD_WARNING; } - rfg->name = strdup (argv[2]->arg); + rfg->name = strdup (argv[1]->arg); /* add to tail of list */ listnode_add (bgp->rfapi_cfg->l2_groups, rfg); } @@ -3336,18 +3841,29 @@ DEFUN (vnc_no_l2_group, { VTY_DECLVAR_CONTEXT(bgp, bgp); + if (!bgp) + { + vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE); + return CMD_WARNING; + } return bgp_rfapi_delete_named_l2_group (vty, bgp, argv[3]->arg); } DEFUN (vnc_l2_group_lni, vnc_l2_group_lni_cmd, - "logical-network-id (0-4294967295)", + "logical-network-id <0-4294967295>", "Specify Logical Network ID associated with group\n" "value\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); VTY_DECLVAR_CONTEXT_SUB(rfapi_l2_group_cfg, rfg); + VTY_DECLVAR_CONTEXT(bgp, bgp); + + if (!bgp) + { + vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE); + return CMD_WARNING; + } /* make sure it's still in list */ if (!listnode_lookup (bgp->rfapi_cfg->l2_groups, rfg)) @@ -3364,14 +3880,20 @@ DEFUN (vnc_l2_group_lni, DEFUN (vnc_l2_group_labels, vnc_l2_group_labels_cmd, - "labels LABELLIST...", + "labels .LABELLIST", "Specify label values associated with group\n" "Space separated list of label values <0-1048575>\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); VTY_DECLVAR_CONTEXT_SUB(rfapi_l2_group_cfg, rfg); + VTY_DECLVAR_CONTEXT(bgp, bgp); struct list *ll; + if (!bgp) + { + vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE); + return CMD_WARNING; + } + /* make sure it's still in list */ if (!listnode_lookup (bgp->rfapi_cfg->l2_groups, rfg)) { @@ -3386,13 +3908,12 @@ DEFUN (vnc_l2_group_labels, ll = list_new (); rfg->labels = ll; } - - argc -= 1; - argv += 1; + argc--; + argv++; for (; argc; --argc, ++argv) { uint32_t label; - VTY_GET_INTEGER_RANGE ("Label value", label, argv[0]->arg, 0, 1048575); + VTY_GET_INTEGER_RANGE ("Label value", label, argv[0]->arg, 0, MPLS_LABEL_MAX); if (!listnode_lookup (ll, (void *) (uintptr_t) label)) listnode_add (ll, (void *) (uintptr_t) label); } @@ -3402,16 +3923,22 @@ DEFUN (vnc_l2_group_labels, DEFUN (vnc_l2_group_no_labels, vnc_l2_group_no_labels_cmd, - "no labels LABELLIST...", + "no labels .LABELLIST", NO_STR "Remove label values associated with L2 group\n" "Specify label values associated with L2 group\n" "Space separated list of label values <0-1048575>\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); VTY_DECLVAR_CONTEXT_SUB(rfapi_l2_group_cfg, rfg); + VTY_DECLVAR_CONTEXT(bgp, bgp); struct list *ll; + if (!bgp) + { + vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE); + return CMD_WARNING; + } + /* make sure it's still in list */ if (!listnode_lookup (bgp->rfapi_cfg->l2_groups, rfg)) { @@ -3427,12 +3954,12 @@ DEFUN (vnc_l2_group_no_labels, return CMD_WARNING; } - argc -= 2; - argv += 2; + argc-=2; + argv+=2; for (; argc; --argc, ++argv) { uint32_t label; - VTY_GET_INTEGER_RANGE ("Label value", label, argv[0]->arg, 0, 1048575); + VTY_GET_INTEGER_RANGE ("Label value", label, argv[0]->arg, 0, MPLS_LABEL_MAX); listnode_delete (ll, (void *) (uintptr_t) label); } @@ -3448,8 +3975,8 @@ DEFUN (vnc_l2_group_rt, "Import filters\n" "A route target\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); VTY_DECLVAR_CONTEXT_SUB(rfapi_l2_group_cfg, rfg); + VTY_DECLVAR_CONTEXT(bgp, bgp); int rc = CMD_SUCCESS; int do_import = 0; int do_export = 0; @@ -3467,10 +3994,8 @@ DEFUN (vnc_l2_group_rt, default: vty_out (vty, "Unknown option, %s%s", argv[1]->arg, VTY_NEWLINE); return CMD_ERR_NO_MATCH; - } - if (argc < 3) - return CMD_ERR_INCOMPLETE; + } if (!bgp) { vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE); @@ -3486,9 +4011,9 @@ DEFUN (vnc_l2_group_rt, } if (do_import) - rc = set_ecom_list (vty, argc - 2, argv + 2, &rfg->rt_import_list); + rc = set_ecom_list (vty, argc-2, argv+2, &rfg->rt_import_list); if (rc == CMD_SUCCESS && do_export) - rc = set_ecom_list (vty, argc - 2, argv + 2, &rfg->rt_export_list); + rc = set_ecom_list (vty, argc-2, argv+2, &rfg->rt_export_list); return rc; } @@ -3571,7 +4096,9 @@ bgp_rfapi_cfg_init (void) install_node (&bgp_vnc_defaults_node, NULL); install_node (&bgp_vnc_nve_group_node, NULL); + install_node (&bgp_vrf_policy_node, NULL); install_node (&bgp_vnc_l2_group_node, NULL); + install_default (BGP_VRF_POLICY_NODE); install_default (BGP_VNC_DEFAULTS_NODE); install_default (BGP_VNC_NVE_GROUP_NODE); install_default (BGP_VNC_L2_GROUP_NODE); @@ -3582,6 +4109,8 @@ bgp_rfapi_cfg_init (void) install_element (BGP_NODE, &vnc_defaults_cmd); install_element (BGP_NODE, &vnc_nve_group_cmd); install_element (BGP_NODE, &vnc_no_nve_group_cmd); + install_element (BGP_NODE, &vnc_vrf_policy_cmd); + install_element (BGP_NODE, &vnc_no_vrf_policy_cmd); install_element (BGP_NODE, &vnc_l2_group_cmd); install_element (BGP_NODE, &vnc_no_l2_group_cmd); install_element (BGP_NODE, &vnc_advertise_un_method_cmd); @@ -3645,6 +4174,16 @@ bgp_rfapi_cfg_init (void) &vnc_nve_group_export_no_routemap_cmd); install_element (BGP_VNC_NVE_GROUP_NODE, &exit_vnc_cmd); + install_element (BGP_VRF_POLICY_NODE, &vnc_vrf_policy_label_cmd); + install_element (BGP_VRF_POLICY_NODE, &vnc_vrf_policy_no_label_cmd); + //Hide per Jan 17 discussion + //install_element (BGP_VRF_POLICY_NODE, &vnc_vrf_policy_nexthop_cmd); + install_element (BGP_VRF_POLICY_NODE, &vnc_vrf_policy_rt_import_cmd); + install_element (BGP_VRF_POLICY_NODE, &vnc_vrf_policy_rt_export_cmd); + install_element (BGP_VRF_POLICY_NODE, &vnc_vrf_policy_rt_both_cmd); + install_element (BGP_VRF_POLICY_NODE, &vnc_vrf_policy_rd_cmd); + install_element (BGP_VRF_POLICY_NODE, &exit_vrf_policy_cmd); + install_element (BGP_VNC_L2_GROUP_NODE, &vnc_l2_group_lni_cmd); install_element (BGP_VNC_L2_GROUP_NODE, &vnc_l2_group_labels_cmd); install_element (BGP_VNC_L2_GROUP_NODE, &vnc_l2_group_no_labels_cmd); @@ -3713,7 +4252,7 @@ bgp_rfapi_cfg_destroy (struct bgp *bgp, struct rfapi_cfg *h) if (h == NULL) return; - bgp_rfapi_delete_named_nve_group (NULL, bgp, NULL); + bgp_rfapi_delete_named_nve_group (NULL, bgp, NULL, RFAPI_GROUP_CFG_MAX); bgp_rfapi_delete_named_l2_group (NULL, bgp, NULL); if (h->l2_groups != NULL) list_delete (h->l2_groups); @@ -3741,6 +4280,166 @@ bgp_rfapi_cfg_write (struct vty *vty, struct bgp *bgp) afi_t afi; int type; + vty_out (vty, "!%s", VTY_NEWLINE); + for (ALL_LIST_ELEMENTS (hc->nve_groups_sequential, node, nnode, rfg)) + if (rfg->type == RFAPI_GROUP_CFG_VRF) + { + ++write; + vty_out (vty, " vrf-policy %s%s", rfg->name, VTY_NEWLINE); + if (rfg->label <= MPLS_LABEL_MAX) + { + vty_out (vty, " label %u%s", rfg->label, VTY_NEWLINE); + + } + if (CHECK_FLAG (rfg->flags, RFAPI_RFG_VPN_NH_SELF)) + { + vty_out (vty, " nexthop self%s", VTY_NEWLINE); + + } + else + { + if (rfg->vn_prefix.family) + { + char buf[BUFSIZ]; + buf[0] = buf[BUFSIZ - 1] = 0; + inet_ntop(rfg->vn_prefix.family, &rfg->vn_prefix.u.prefix, buf, sizeof(buf)); + if (!buf[0] || buf[BUFSIZ - 1]) + { + //vty_out (vty, "nexthop self%s", VTY_NEWLINE); + } + else + { + vty_out (vty, " nexthop %s%s", buf, VTY_NEWLINE); + } + } + } + + if (rfg->rd.prefixlen) + { + char buf[BUFSIZ]; + buf[0] = buf[BUFSIZ - 1] = 0; + + if (AF_UNIX == rfg->rd.family) + { + + uint16_t value = 0; + + value = ((rfg->rd.val[6] << 8) & 0x0ff00) | + (rfg->rd.val[7] & 0x0ff); + + vty_out (vty, " rd auto:nh:%d%s", value, VTY_NEWLINE); + + } + else + { + + if (!prefix_rd2str (&rfg->rd, buf, BUFSIZ) || + !buf[0] || buf[BUFSIZ - 1]) + { + + vty_out (vty, "!Error: Can't convert rd%s", VTY_NEWLINE); + } + else + { + vty_out (vty, " rd %s%s", buf, VTY_NEWLINE); + } + } + } + + if (rfg->rt_import_list && rfg->rt_export_list && + ecommunity_cmp (rfg->rt_import_list, rfg->rt_export_list)) + { + char *b = ecommunity_ecom2str (rfg->rt_import_list, + ECOMMUNITY_FORMAT_ROUTE_MAP); + vty_out (vty, " rt both %s%s", b, VTY_NEWLINE); + XFREE (MTYPE_ECOMMUNITY_STR, b); + } + else + { + if (rfg->rt_import_list) + { + char *b = ecommunity_ecom2str (rfg->rt_import_list, + ECOMMUNITY_FORMAT_ROUTE_MAP); + vty_out (vty, " rt import %s%s", b, VTY_NEWLINE); + XFREE (MTYPE_ECOMMUNITY_STR, b); + } + if (rfg->rt_export_list) + { + char *b = ecommunity_ecom2str (rfg->rt_export_list, + ECOMMUNITY_FORMAT_ROUTE_MAP); + vty_out (vty, " rt export %s%s", b, VTY_NEWLINE); + XFREE (MTYPE_ECOMMUNITY_STR, b); + } + } + + /* + * route filtering: prefix-lists and route-maps + */ + for (afi = AFI_IP; afi < AFI_MAX; ++afi) + { + + const char *afistr = (afi == AFI_IP) ? "ipv4" : "ipv6"; + + if (rfg->plist_export_bgp_name[afi]) + { + vty_out (vty, " export bgp %s prefix-list %s%s", + afistr, rfg->plist_export_bgp_name[afi], + VTY_NEWLINE); + } + if (rfg->plist_export_zebra_name[afi]) + { + vty_out (vty, " export zebra %s prefix-list %s%s", + afistr, rfg->plist_export_zebra_name[afi], + VTY_NEWLINE); + } + /* + * currently we only support redist plists for bgp-direct. + * If we later add plist support for redistributing other + * protocols, we'll need to loop over protocols here + */ + if (rfg->plist_redist_name[ZEBRA_ROUTE_BGP_DIRECT][afi]) + { + vty_out (vty, " redistribute bgp-direct %s prefix-list %s%s", + afistr, + rfg->plist_redist_name[ZEBRA_ROUTE_BGP_DIRECT][afi], + VTY_NEWLINE); + } + if (rfg->plist_redist_name[ZEBRA_ROUTE_BGP_DIRECT_EXT][afi]) + { + vty_out (vty, + " redistribute bgp-direct-to-nve-groups %s prefix-list %s%s", + afistr, + rfg->plist_redist_name[ZEBRA_ROUTE_BGP_DIRECT_EXT] + [afi], VTY_NEWLINE); + } + } + + if (rfg->routemap_export_bgp_name) + { + vty_out (vty, " export bgp route-map %s%s", + rfg->routemap_export_bgp_name, VTY_NEWLINE); + } + if (rfg->routemap_export_zebra_name) + { + vty_out (vty, " export zebra route-map %s%s", + rfg->routemap_export_zebra_name, VTY_NEWLINE); + } + if (rfg->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT]) + { + vty_out (vty, " redistribute bgp-direct route-map %s%s", + rfg->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT], + VTY_NEWLINE); + } + if (rfg->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT_EXT]) + { + vty_out (vty, + " redistribute bgp-direct-to-nve-groups route-map %s%s", + rfg->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT_EXT], + VTY_NEWLINE); + } + vty_out (vty, " exit-vrf-policy%s", VTY_NEWLINE); + vty_out (vty, "!%s", VTY_NEWLINE); + } if (hc->flags & BGP_VNC_CONFIG_ADV_UN_METHOD_ENCAP) { vty_out (vty, " vnc advertise-un-method encap-safi%s", VTY_NEWLINE); @@ -3902,6 +4601,7 @@ bgp_rfapi_cfg_write (struct vty *vty, struct bgp *bgp) } for (ALL_LIST_ELEMENTS (hc->nve_groups_sequential, node, nnode, rfg)) + if (rfg->type == RFAPI_GROUP_CFG_NVE) { ++write; vty_out (vty, " vnc nve-group %s%s", rfg->name, VTY_NEWLINE); diff --git a/bgpd/rfapi/bgp_rfapi_cfg.h b/bgpd/rfapi/bgp_rfapi_cfg.h index 897b4be76..8f93d69f6 100644 --- a/bgpd/rfapi/bgp_rfapi_cfg.h +++ b/bgpd/rfapi/bgp_rfapi_cfg.h @@ -41,12 +41,21 @@ struct rfapi_l2_group_cfg }; DECLARE_QOBJ_TYPE(rfapi_l2_group_cfg) +typedef enum +{ + RFAPI_GROUP_CFG_NVE = 1, + RFAPI_GROUP_CFG_VRF, + RFAPI_GROUP_CFG_L2, + RFAPI_GROUP_CFG_MAX +} rfapi_group_cfg_type_t; + struct rfapi_nve_group_cfg { struct route_node *vn_node; /* backref */ struct route_node *un_node; /* backref */ - char *name; + rfapi_group_cfg_type_t type; /* NVE|VPN */ + char *name; /* unique by type! */ struct prefix vn_prefix; struct prefix un_prefix; @@ -54,8 +63,9 @@ struct rfapi_nve_group_cfg uint8_t l2rd; /* 0 = VN addr LSB */ uint32_t response_lifetime; uint32_t flags; -#define RFAPI_RFG_RESPONSE_LIFETIME 0x1 +#define RFAPI_RFG_RESPONSE_LIFETIME 0x01 /* bits */ #define RFAPI_RFG_L2RD 0x02 +#define RFAPI_RFG_VPN_NH_SELF 0x04 struct ecommunity *rt_import_list; struct ecommunity *rt_export_list; struct rfapi_import_table *rfapi_import_table; @@ -99,6 +109,9 @@ struct rfapi_nve_group_cfg char *routemap_redist_name[ZEBRA_ROUTE_MAX]; struct route_map *routemap_redist[ZEBRA_ROUTE_MAX]; + /* for VRF type groups */ + uint32_t label; + struct rfapi_descriptor *rfd; QOBJ_FIELDS }; DECLARE_QOBJ_TYPE(rfapi_nve_group_cfg) @@ -288,6 +301,12 @@ bgp_rfapi_cfg_match_group ( struct prefix *vn, struct prefix *un); +struct rfapi_nve_group_cfg * +bgp_rfapi_cfg_match_byname ( + struct bgp *bgp, + const char *name, + rfapi_group_cfg_type_t type); /* _MAX = any */ + extern void vnc_prefix_list_update (struct bgp *bgp); diff --git a/bgpd/rfapi/rfapi.c b/bgpd/rfapi/rfapi.c index 61da18a30..c195d09ce 100644 --- a/bgpd/rfapi/rfapi.c +++ b/bgpd/rfapi/rfapi.c @@ -335,6 +335,9 @@ is_valid_rfd (struct rfapi_descriptor *rfd) if (!rfd || rfd->bgp == NULL) return 0; + if (CHECK_FLAG(rfd->flags, RFAPI_HD_FLAG_IS_VRF)) /* assume VRF/internal are valid */ + return 1; + if (rfapi_find_handle (rfd->bgp, &rfd->vn_addr, &rfd->un_addr, &hh)) return 0; @@ -357,6 +360,9 @@ rfapi_check (void *handle) if (!rfd || rfd->bgp == NULL) return EINVAL; + if (CHECK_FLAG(rfd->flags, RFAPI_HD_FLAG_IS_VRF)) /* assume VRF/internal are valid */ + return 0; + if ((rc = rfapi_find_handle (rfd->bgp, &rfd->vn_addr, &rfd->un_addr, &hh))) return rc; @@ -1347,7 +1353,6 @@ rfapi_rfp_set_cb_methods (void *rfp_start_val, /*********************************************************************** * NVE Sessions ***********************************************************************/ - /* * Caller must supply an already-allocated rfd with the "caller" * fields already set (vn_addr, un_addr, callback, cookie) @@ -1474,6 +1479,57 @@ rfapi_open_inner ( return 0; } +/* moved from rfapi_register */ +int +rfapi_init_and_open( + struct bgp *bgp, + struct rfapi_descriptor *rfd, + struct rfapi_nve_group_cfg *rfg) +{ + struct rfapi *h = bgp->rfapi; + char buf_vn[BUFSIZ]; + char buf_un[BUFSIZ]; + afi_t afi_vn, afi_un; + struct prefix pfx_un; + struct route_node *rn; + + + rfapi_time (&rfd->open_time); + + if (rfg->type == RFAPI_GROUP_CFG_VRF) + SET_FLAG(rfd->flags, RFAPI_HD_FLAG_IS_VRF); + + rfapiRfapiIpAddr2Str (&rfd->vn_addr, buf_vn, BUFSIZ); + rfapiRfapiIpAddr2Str (&rfd->un_addr, buf_un, BUFSIZ); + + vnc_zlog_debug_verbose ("%s: new RFD with VN=%s UN=%s cookie=%p", + __func__, buf_vn, buf_un, rfd->cookie); + + if (rfg->type != RFAPI_GROUP_CFG_VRF) /* unclear if needed for VRF */ + { + listnode_add (&h->descriptors, rfd); + if (h->descriptors.count > h->stat.max_descriptors) + { + h->stat.max_descriptors = h->descriptors.count; + } + + /* + * attach to UN radix tree + */ + afi_vn = family2afi (rfd->vn_addr.addr_family); + afi_un = family2afi (rfd->un_addr.addr_family); + assert (afi_vn && afi_un); + assert (!rfapiRaddr2Qprefix (&rfd->un_addr, &pfx_un)); + + rn = route_node_get (&(h->un[afi_un]), &pfx_un); + assert (rn); + rfd->next = rn->info; + rn->info = rfd; + rfd->un_node = rn; + } + return rfapi_open_inner (rfd, bgp, h, rfg); +} + struct rfapi_vn_option * rfapiVnOptionsDup (struct rfapi_vn_option *orig) { @@ -1991,14 +2047,10 @@ rfapi_open ( struct prefix pfx_vn; struct prefix pfx_un; - struct route_node *rn; int rc; rfapi_handle hh = NULL; int reusing_provisional = 0; - afi_t afi_vn; - afi_t afi_un; - { char buf[2][INET_ADDRSTRLEN]; vnc_zlog_debug_verbose ("%s: VN=%s UN=%s", __func__, @@ -2129,40 +2181,7 @@ rfapi_open ( if (!reusing_provisional) { - rfapi_time (&rfd->open_time); - - { - char buf_vn[BUFSIZ]; - char buf_un[BUFSIZ]; - - rfapiRfapiIpAddr2Str (vn, buf_vn, BUFSIZ); - rfapiRfapiIpAddr2Str (un, buf_un, BUFSIZ); - - vnc_zlog_debug_verbose ("%s: new HD with VN=%s UN=%s cookie=%p", - __func__, buf_vn, buf_un, userdata); - } - - listnode_add (&h->descriptors, rfd); - if (h->descriptors.count > h->stat.max_descriptors) - { - h->stat.max_descriptors = h->descriptors.count; - } - - /* - * attach to UN radix tree - */ - afi_vn = family2afi (rfd->vn_addr.addr_family); - afi_un = family2afi (rfd->un_addr.addr_family); - assert (afi_vn && afi_un); - assert (!rfapiRaddr2Qprefix (&rfd->un_addr, &pfx_un)); - - rn = route_node_get (&(h->un[afi_un]), &pfx_un); - assert (rn); - rfd->next = rn->info; - rn->info = rfd; - rfd->un_node = rn; - - rc = rfapi_open_inner (rfd, bgp, h, rfg); + rc = rfapi_init_and_open(bgp, rfd, rfg); /* * This can fail only if the VN address is IPv6 and the group * specified auto-assignment of RDs, which only works for v4, @@ -2777,7 +2796,7 @@ rfapi_register ( NULL, action == RFAPI_REGISTER_KILL); - if (0 == rfapiApDelete (bgp, rfd, &p, pfx_mac, &adv_tunnel)) + if (0 == rfapiApDelete (bgp, rfd, &p, pfx_mac, &prd, &adv_tunnel)) { if (adv_tunnel) rfapiTunnelRouteAnnounce (bgp, rfd, &rfd->max_prefix_lifetime); diff --git a/bgpd/rfapi/rfapi_ap.c b/bgpd/rfapi/rfapi_ap.c index 4b8eb9511..4c415504f 100644 --- a/bgpd/rfapi/rfapi_ap.c +++ b/bgpd/rfapi/rfapi_ap.c @@ -103,12 +103,11 @@ sl_adb_lifetime_cmp (void *adb1, void *adb2) return 0; } - void rfapiApInit (struct rfapi_advertised_prefixes *ap) { - ap->ipN_by_prefix = skiplist_new (0, vnc_prefix_cmp, NULL); - ap->ip0_by_ether = skiplist_new (0, vnc_prefix_cmp, NULL); + ap->ipN_by_prefix = skiplist_new (0, rfapi_rib_key_cmp, NULL); + ap->ip0_by_ether = skiplist_new (0, rfapi_rib_key_cmp, NULL); ap->by_lifetime = skiplist_new (0, sl_adb_lifetime_cmp, NULL); } @@ -192,7 +191,7 @@ rfapiApReadvertiseAll (struct bgp *bgp, struct rfapi_descriptor *rfd) * TBD this is not quite right. When pfx_ip is 0/32 or 0/128, * we need to substitute the VN address as the prefix */ - add_vnc_route (rfd, bgp, SAFI_MPLS_VPN, &adb->prefix_ip, &prd, /* RD to use (0 for ENCAP) */ + add_vnc_route (rfd, bgp, SAFI_MPLS_VPN, &adb->u.s.prefix_ip, &prd, /* RD to use (0 for ENCAP) */ &rfd->vn_addr, /* nexthop */ &local_pref, &adb->lifetime, NULL, NULL, /* struct rfapi_un_option */ NULL, /* struct rfapi_vn_option */ @@ -221,11 +220,11 @@ rfapiApWithdrawAll (struct bgp *bgp, struct rfapi_descriptor *rfd) struct prefix pfx_vn_buf; struct prefix *pfx_ip; - if (!(RFAPI_0_PREFIX (&adb->prefix_ip) && - RFAPI_HOST_PREFIX (&adb->prefix_ip))) + if (!(RFAPI_0_PREFIX (&adb->u.s.prefix_ip) && + RFAPI_HOST_PREFIX (&adb->u.s.prefix_ip))) { - pfx_ip = &adb->prefix_ip; + pfx_ip = &adb->u.s.prefix_ip; } else @@ -247,7 +246,7 @@ rfapiApWithdrawAll (struct bgp *bgp, struct rfapi_descriptor *rfd) } } - del_vnc_route (rfd, rfd->peer, bgp, SAFI_MPLS_VPN, pfx_ip ? pfx_ip : &pfx_vn_buf, &adb->prd, /* RD to use (0 for ENCAP) */ + del_vnc_route (rfd, rfd->peer, bgp, SAFI_MPLS_VPN, pfx_ip ? pfx_ip : &pfx_vn_buf, &adb->u.s.prd, /* RD to use (0 for ENCAP) */ ZEBRA_ROUTE_BGP, BGP_ROUTE_RFP, NULL, 0); } } @@ -404,19 +403,19 @@ rfapiApAdjustLifetimeStats ( { void *cursor; - struct prefix *prefix; - struct rfapi_adb *adb; + struct rfapi_rib_key rk; + struct rfapi_adb *adb; int rc; vnc_zlog_debug_verbose ("%s: walking to find new min/max", __func__); cursor = NULL; for (rc = skiplist_next (rfd->advertised.ipN_by_prefix, - (void **) &prefix, (void **) &adb, + (void **) &rk, (void **) &adb, &cursor); !rc; rc = skiplist_next (rfd->advertised.ipN_by_prefix, - (void **) &prefix, (void **) &adb, &cursor)) + (void **) &rk, (void **) &adb, &cursor)) { uint32_t lt = adb->lifetime; @@ -428,10 +427,10 @@ rfapiApAdjustLifetimeStats ( } cursor = NULL; for (rc = skiplist_next (rfd->advertised.ip0_by_ether, - (void **) &prefix, (void **) &adb, + (void **) &rk, (void **) &adb, &cursor); !rc; rc = - skiplist_next (rfd->advertised.ip0_by_ether, (void **) &prefix, + skiplist_next (rfd->advertised.ip0_by_ether, (void **) &rk, (void **) &adb, &cursor)) { @@ -483,14 +482,15 @@ rfapiApAdd ( struct rfapi_adb *adb; uint32_t old_lifetime = 0; int use_ip0 = 0; + struct rfapi_rib_key rk; + rfapi_rib_key_init(pfx_ip, prd, pfx_eth, &rk); if (RFAPI_0_PREFIX (pfx_ip) && RFAPI_HOST_PREFIX (pfx_ip)) { use_ip0 = 1; assert (pfx_eth); - rc = - skiplist_search (rfd->advertised.ip0_by_ether, pfx_eth, + skiplist_search (rfd->advertised.ip0_by_ether, &rk, (void **) &adb); } @@ -499,7 +499,7 @@ rfapiApAdd ( /* find prefix in advertised prefixes list */ rc = - skiplist_search (rfd->advertised.ipN_by_prefix, pfx_ip, + skiplist_search (rfd->advertised.ipN_by_prefix, &rk, (void **) &adb); } @@ -510,19 +510,17 @@ rfapiApAdd ( adb = XCALLOC (MTYPE_RFAPI_ADB, sizeof (struct rfapi_adb)); assert (adb); adb->lifetime = lifetime; - adb->prefix_ip = *pfx_ip; - if (pfx_eth) - adb->prefix_eth = *pfx_eth; + adb->u.key = rk; if (use_ip0) { assert (pfx_eth); - skiplist_insert (rfd->advertised.ip0_by_ether, &adb->prefix_eth, + skiplist_insert (rfd->advertised.ip0_by_ether, &adb->u.key, adb); } else { - skiplist_insert (rfd->advertised.ipN_by_prefix, &adb->prefix_ip, + skiplist_insert (rfd->advertised.ipN_by_prefix, &adb->u.key, adb); } @@ -537,19 +535,12 @@ rfapiApAdd ( adb->lifetime = lifetime; assert (!skiplist_insert (rfd->advertised.by_lifetime, adb, adb)); } - - if (!use_ip0 && pfx_eth && prefix_cmp (&adb->prefix_eth, pfx_eth)) - { - /* mac address changed */ - adb->prefix_eth = *pfx_eth; - } } adb->cost = cost; if (l2o) adb->l2o = *l2o; else memset (&adb->l2o, 0, sizeof (struct rfapi_l2address_option)); - adb->prd = *prd; if (rfapiApAdjustLifetimeStats (rfd, (rc ? NULL : &old_lifetime), &lifetime)) @@ -568,16 +559,19 @@ rfapiApDelete ( struct rfapi_descriptor *rfd, struct prefix *pfx_ip, struct prefix *pfx_eth, + struct prefix_rd *prd, int *advertise_tunnel) /* out */ { int rc; struct rfapi_adb *adb; uint32_t old_lifetime; int use_ip0 = 0; + struct rfapi_rib_key rk; if (advertise_tunnel) *advertise_tunnel = 0; + rfapi_rib_key_init(pfx_ip, prd, pfx_eth, &rk); /* find prefix in advertised prefixes list */ if (RFAPI_0_PREFIX (pfx_ip) && RFAPI_HOST_PREFIX (pfx_ip)) { @@ -585,7 +579,7 @@ rfapiApDelete ( assert (pfx_eth); rc = - skiplist_search (rfd->advertised.ip0_by_ether, pfx_eth, + skiplist_search (rfd->advertised.ip0_by_ether, &rk, (void **) &adb); } @@ -594,7 +588,7 @@ rfapiApDelete ( /* find prefix in advertised prefixes list */ rc = - skiplist_search (rfd->advertised.ipN_by_prefix, pfx_ip, + skiplist_search (rfd->advertised.ipN_by_prefix, &rk, (void **) &adb); } @@ -607,11 +601,11 @@ rfapiApDelete ( if (use_ip0) { - rc = skiplist_delete (rfd->advertised.ip0_by_ether, pfx_eth, NULL); + rc = skiplist_delete (rfd->advertised.ip0_by_ether, &rk, NULL); } else { - rc = skiplist_delete (rfd->advertised.ipN_by_prefix, pfx_ip, NULL); + rc = skiplist_delete (rfd->advertised.ipN_by_prefix, &rk, NULL); } assert (!rc); diff --git a/bgpd/rfapi/rfapi_ap.h b/bgpd/rfapi/rfapi_ap.h index f2805f49c..8a59f0527 100644 --- a/bgpd/rfapi/rfapi_ap.h +++ b/bgpd/rfapi/rfapi_ap.h @@ -93,6 +93,7 @@ rfapiApDelete ( struct rfapi_descriptor *rfd, struct prefix *pfx_ip, struct prefix *pfx_eth, + struct prefix_rd *prd, int *advertise_tunnel); /* out */ diff --git a/bgpd/rfapi/rfapi_backend.h b/bgpd/rfapi/rfapi_backend.h index 788ec7375..9e5b0dc5c 100644 --- a/bgpd/rfapi/rfapi_backend.h +++ b/bgpd/rfapi/rfapi_backend.h @@ -36,15 +36,6 @@ extern void rfapi_delete (struct bgp *); struct rfapi *bgp_rfapi_new (struct bgp *bgp); void bgp_rfapi_destroy (struct bgp *bgp, struct rfapi *h); -struct rfapi_import_table *rfapiImportTableRefAdd (struct bgp *bgp, - struct ecommunity - *rt_import_list); - -void -rfapiImportTableRefDelByIt (struct bgp *bgp, - struct rfapi_import_table *it_target); - - extern void rfapiProcessUpdate (struct peer *peer, void *rfd, diff --git a/bgpd/rfapi/rfapi_import.c b/bgpd/rfapi/rfapi_import.c index e6fdb7180..1cd12ca0d 100644 --- a/bgpd/rfapi/rfapi_import.c +++ b/bgpd/rfapi/rfapi_import.c @@ -4644,7 +4644,8 @@ bgp_rfapi_destroy (struct bgp *bgp, struct rfapi *h) } struct rfapi_import_table * -rfapiImportTableRefAdd (struct bgp *bgp, struct ecommunity *rt_import_list) +rfapiImportTableRefAdd (struct bgp *bgp, struct ecommunity *rt_import_list, + struct rfapi_nve_group_cfg *rfg) { struct rfapi *h; struct rfapi_import_table *it; @@ -4670,6 +4671,7 @@ rfapiImportTableRefAdd (struct bgp *bgp, struct ecommunity *rt_import_list) h->imports = it; it->rt_import_list = ecommunity_dup (rt_import_list); + it->rfg = rfg; it->monitor_exterior_orphans = skiplist_new (0, NULL, (void (*)(void *)) prefix_free); @@ -4943,6 +4945,7 @@ rfapiDeleteRemotePrefixesIt ( * un if set, tunnel must match this prefix * vn if set, nexthop prefix must match this prefix * p if set, prefix must match this prefix + * it if set, only look in this import table * * output * pARcount number of active routes deleted @@ -4958,6 +4961,7 @@ rfapiDeleteRemotePrefixes ( struct prefix *un, struct prefix *vn, struct prefix *p, + struct rfapi_import_table *arg_it, int delete_active, int delete_holddown, uint32_t *pARcount, @@ -4995,7 +4999,11 @@ rfapiDeleteRemotePrefixes ( * for the afi/safi combination */ - for (it = h->imports; it; it = it->next) + if (arg_it) + it = arg_it; + else + it = h->imports; + for (; it; ) { vnc_zlog_debug_verbose @@ -5016,6 +5024,11 @@ rfapiDeleteRemotePrefixes ( &deleted_holddown_nve_count, uniq_active_nves, uniq_holddown_nves); + + if (arg_it) + it = NULL; + else + it = it->next; } /* diff --git a/bgpd/rfapi/rfapi_import.h b/bgpd/rfapi/rfapi_import.h index 3cf55462a..3ba76539d 100644 --- a/bgpd/rfapi/rfapi_import.h +++ b/bgpd/rfapi/rfapi_import.h @@ -38,6 +38,7 @@ struct rfapi_import_table { struct rfapi_import_table *next; + struct rfapi_nve_group_cfg *rfg; struct ecommunity *rt_import_list; /* copied from nve grp */ int refcount; /* nve grps and nves */ uint32_t l2_logical_net_id; /* L2 only: EVPN Eth Seg Id */ @@ -90,6 +91,11 @@ rfapiShowImportTable ( struct route_table *rt, int isvpn); +extern struct rfapi_import_table * +rfapiImportTableRefAdd ( + struct bgp *bgp, + struct ecommunity *rt_import_list, + struct rfapi_nve_group_cfg *rfg); extern void rfapiImportTableRefDelByIt ( @@ -223,6 +229,7 @@ extern int rfapiEcommunityGetEthernetTag ( * un if set, tunnel must match this prefix * vn if set, nexthop prefix must match this prefix * p if set, prefix must match this prefix + * it if set, only look in this import table * * output * pARcount number of active routes deleted @@ -238,6 +245,7 @@ rfapiDeleteRemotePrefixes ( struct prefix *un, struct prefix *vn, struct prefix *p, + struct rfapi_import_table *it, int delete_active, int delete_holddown, uint32_t *pARcount, /* active routes */ diff --git a/bgpd/rfapi/rfapi_private.h b/bgpd/rfapi/rfapi_private.h index 33390c4f5..ed83ef1e1 100644 --- a/bgpd/rfapi/rfapi_private.h +++ b/bgpd/rfapi/rfapi_private.h @@ -35,21 +35,6 @@ #include "rfapi.h" /* - * RFAPI Advertisement Data Block - * - * Holds NVE prefix advertisement information - */ -struct rfapi_adb -{ - struct prefix prefix_ip; - struct prefix prefix_eth; /* now redundant with l2o */ - struct prefix_rd prd; - uint32_t lifetime; - uint8_t cost; - struct rfapi_l2address_option l2o; -}; - -/* * Lists of rfapi_adb. Each rfapi_adb is referenced twice: * * 1. each is referenced in by_lifetime @@ -62,7 +47,6 @@ struct rfapi_advertised_prefixes struct skiplist *by_lifetime; /* all */ }; - struct rfapi_descriptor { struct route_node *un_node; /* backref to un table */ @@ -151,6 +135,7 @@ struct rfapi_descriptor #define RFAPI_HD_FLAG_CALLBACK_SCHEDULED_AFI_ETHER 0x00000004 #define RFAPI_HD_FLAG_PROVISIONAL 0x00000008 #define RFAPI_HD_FLAG_CLOSING_ADMINISTRATIVELY 0x00000010 +#define RFAPI_HD_FLAG_IS_VRF 0x00000012 }; #define RFAPI_QUEUED_FLAG(afi) ( \ @@ -378,9 +363,6 @@ rfp_cost_to_localpref (uint8_t cost); extern int rfapi_set_autord_from_vn (struct prefix_rd *rd, struct rfapi_ip_addr *vn); -extern void -rfapiAdbFree (struct rfapi_adb *adb); - extern struct rfapi_nexthop * rfapi_nexthop_new (struct rfapi_nexthop *copyme); @@ -452,4 +434,17 @@ DECLARE_MTYPE(RFAPI_L2ADDR_OPT) DECLARE_MTYPE(RFAPI_AP) DECLARE_MTYPE(RFAPI_MONITOR_ETH) + +/* + * Caller must supply an already-allocated rfd with the "caller" + * fields already set (vn_addr, un_addr, callback, cookie) + * The advertised_prefixes[] array elements should be NULL to + * have this function set them to newly-allocated radix trees. + */ +extern int +rfapi_init_and_open( + struct bgp *bgp, + struct rfapi_descriptor *rfd, + struct rfapi_nve_group_cfg *rfg); + #endif /* _QUAGGA_BGP_RFAPI_PRIVATE_H */ diff --git a/bgpd/rfapi/rfapi_rib.c b/bgpd/rfapi/rfapi_rib.c index 6aae35e63..8e5d47415 100644 --- a/bgpd/rfapi/rfapi_rib.c +++ b/bgpd/rfapi/rfapi_rib.c @@ -405,10 +405,26 @@ rfapiRibStartTimer ( assert (ri->timer); } +extern void +rfapi_rib_key_init (struct prefix *prefix, /* may be NULL */ + struct prefix_rd *rd, /* may be NULL */ + struct prefix *aux, /* may be NULL */ + struct rfapi_rib_key *rk) + +{ + memset((void *)rk, 0, sizeof(struct rfapi_rib_key)); + if (prefix) + rk->vn = *prefix; + if (rd) + rk->rd = *rd; + if (aux) + rk->aux_prefix = *aux; +} + /* * Compares two <struct rfapi_rib_key>s */ -static int +int rfapi_rib_key_cmp (void *k1, void *k2) { struct rfapi_rib_key *a = (struct rfapi_rib_key *) k1; @@ -498,9 +514,13 @@ rfapi_info_cmp (struct rfapi_info *a, struct rfapi_info *b) void rfapiRibClear (struct rfapi_descriptor *rfd) { - struct bgp *bgp = bgp_get_default (); + struct bgp *bgp; afi_t afi; + if (rfd->bgp) + bgp = rfd->bgp; + else + bgp = bgp_get_default (); #if DEBUG_L2_EXTRA vnc_zlog_debug_verbose ("%s: rfd=%p", __func__, rfd); #endif diff --git a/bgpd/rfapi/rfapi_rib.h b/bgpd/rfapi/rfapi_rib.h index 2a111946f..74331a28d 100644 --- a/bgpd/rfapi/rfapi_rib.h +++ b/bgpd/rfapi/rfapi_rib.h @@ -45,6 +45,27 @@ struct rfapi_rib_key */ struct prefix aux_prefix; }; +#include "rfapi.h" + +/* + * RFAPI Advertisement Data Block + * + * Holds NVE prefix advertisement information + */ +struct rfapi_adb +{ + union { + struct { + struct prefix prefix_ip; + struct prefix_rd prd; + struct prefix prefix_eth; + } s; /* mainly for legacy use */ + struct rfapi_rib_key key; + } u; + uint32_t lifetime; + uint8_t cost; + struct rfapi_l2address_option l2o; +}; struct rfapi_info { @@ -151,4 +172,16 @@ rfapiRibCheckCounts ( #define RFAPI_RIB_CHECK_COUNTS(checkstats, offset) #endif +extern void +rfapi_rib_key_init (struct prefix *prefix, /* may be NULL */ + struct prefix_rd *rd, /* may be NULL */ + struct prefix *aux, /* may be NULL */ + struct rfapi_rib_key *rk); + +extern int +rfapi_rib_key_cmp (void *k1, void *k2); + +extern void +rfapiAdbFree (struct rfapi_adb *adb); + #endif /* QUAGGA_HGP_RFAPI_RIB_H */ diff --git a/bgpd/rfapi/rfapi_vty.c b/bgpd/rfapi/rfapi_vty.c index 3e179b7f7..7fbfae295 100644 --- a/bgpd/rfapi/rfapi_vty.c +++ b/bgpd/rfapi/rfapi_vty.c @@ -1446,17 +1446,24 @@ rfapiShowRemoteRegistrationsIt ( if (pLni) { - fp (out, "%s[%s] L2VPN Network 0x%x (%u) RT={%s}%s", - HVTY_NEWLINE, type, *pLni, (*pLni & 0xfff), s, - HVTY_NEWLINE); + fp (out, "%s[%s] L2VPN Network 0x%x (%u) RT={%s}", + HVTY_NEWLINE, type, *pLni, (*pLni & 0xfff), s); } else { - fp (out, "%s[%s] Prefix RT={%s}%s", - HVTY_NEWLINE, type, s, HVTY_NEWLINE); + fp (out, "%s[%s] Prefix RT={%s}", + HVTY_NEWLINE, type, s); } XFREE (MTYPE_ECOMMUNITY_STR, s); + if (it->rfg && it->rfg->name) + { + fp (out, " %s \"%s\"", + (it->rfg->type == RFAPI_GROUP_CFG_VRF ? + "VRF" : "NVE group"), + it->rfg->name); + } + fp (out, "%s", HVTY_NEWLINE); if (show_expiring) { #if RFAPI_REGISTRATIONS_REPORT_AGE @@ -1846,14 +1853,14 @@ rfapiPrintDescriptor (struct vty *vty, struct rfapi_descriptor *rfd) { /* group like family prefixes together in output */ - if (family != adb->prefix_ip.family) + if (family != adb->u.s.prefix_ip.family) continue; - prefix2str (&adb->prefix_ip, buf, BUFSIZ); + prefix2str (&adb->u.s.prefix_ip, buf, BUFSIZ); buf[BUFSIZ - 1] = 0; /* guarantee NUL-terminated */ vty_out (vty, " Adv Pfx: %s%s", buf, HVTY_NEWLINE); - rfapiPrintAdvertisedInfo (vty, rfd, SAFI_MPLS_VPN, &adb->prefix_ip); + rfapiPrintAdvertisedInfo (vty, rfd, SAFI_MPLS_VPN, &adb->u.s.prefix_ip); } } for (rc = @@ -1864,14 +1871,14 @@ rfapiPrintDescriptor (struct vty *vty, struct rfapi_descriptor *rfd) &cursor)) { - prefix2str (&adb->prefix_eth, buf, BUFSIZ); + prefix2str (&adb->u.s.prefix_eth, buf, BUFSIZ); buf[BUFSIZ - 1] = 0; /* guarantee NUL-terminated */ vty_out (vty, " Adv Pfx: %s%s", buf, HVTY_NEWLINE); /* TBD update the following function to print ethernet info */ /* Also need to pass/use rd */ - rfapiPrintAdvertisedInfo (vty, rfd, SAFI_MPLS_VPN, &adb->prefix_ip); + rfapiPrintAdvertisedInfo (vty, rfd, SAFI_MPLS_VPN, &adb->u.s.prefix_ip); } vty_out (vty, "%s", HVTY_NEWLINE); } @@ -3004,9 +3011,12 @@ struct rfapi_local_reg_delete_arg /* * match parameters */ + struct bgp *bgp; struct rfapi_ip_addr un_address; /* AF==0: wildcard */ struct rfapi_ip_addr vn_address; /* AF==0: wildcard */ struct prefix prefix; /* AF==0: wildcard */ + struct prefix_rd rd; /* plen!=64: wildcard */ + struct rfapi_nve_group_cfg *rfg; /* NULL: wildcard */ struct rfapi_l2address_option_match l2o; @@ -3106,22 +3116,26 @@ nve_addr_cmp (void *k1, void *k2) static int parse_deleter_args ( - struct vty *vty, - struct cmd_token *carg_prefix, - struct cmd_token *carg_vn, - struct cmd_token *carg_un, - struct cmd_token *carg_l2addr, - struct cmd_token *carg_vni, - struct rfapi_local_reg_delete_arg *rcdarg) + struct vty *vty, + struct bgp *bgp, + const char *arg_prefix, + const char *arg_vn, + const char *arg_un, + const char *arg_l2addr, + const char *arg_vni, + const char *arg_rd, + struct rfapi_nve_group_cfg *arg_rfg, + struct rfapi_local_reg_delete_arg *rcdarg) { - const char *arg_prefix = carg_prefix ? carg_prefix->arg : NULL; - const char *arg_vn = carg_vn ? carg_vn->arg : NULL; - const char *arg_un = carg_un ? carg_un->arg : NULL; - const char *arg_l2addr = carg_l2addr ? carg_l2addr->arg : NULL; - const char *arg_vni = carg_vni ? carg_vni->arg : NULL; int rc = CMD_WARNING; - memset (rcdarg, 0, sizeof (struct rfapi_local_reg_delete_arg)); + memset (rcdarg, 0, sizeof (struct rfapi_local_reg_delete_arg)); + + rcdarg->vty = vty; + if (bgp == NULL) + bgp = bgp_get_default(); + rcdarg->bgp = bgp; + rcdarg->rfg = arg_rfg; /* may be NULL */ if (arg_vn && strcmp (arg_vn, "*")) { @@ -3167,7 +3181,41 @@ parse_deleter_args ( rcdarg->l2o.flags |= RFAPI_L2O_LNI; } } - return 0; + if (arg_rd) + { + if (!str2prefix_rd (arg_rd, &rcdarg->rd)) + { + vty_out (vty, "Malformed RD \"%s\"%s", + arg_rd, VTY_NEWLINE); + return rc; + } + } + + return CMD_SUCCESS; +} + +static int +parse_deleter_tokens ( + struct vty *vty, + struct bgp *bgp, + struct cmd_token *carg_prefix, + struct cmd_token *carg_vn, + struct cmd_token *carg_un, + struct cmd_token *carg_l2addr, + struct cmd_token *carg_vni, + struct cmd_token *carg_rd, + struct rfapi_nve_group_cfg *arg_rfg, + struct rfapi_local_reg_delete_arg *rcdarg) +{ + const char *arg_prefix = carg_prefix ? carg_prefix->arg : NULL; + const char *arg_vn = carg_vn ? carg_vn->arg : NULL; + const char *arg_un = carg_un ? carg_un->arg : NULL; + const char *arg_l2addr = carg_l2addr ? carg_l2addr->arg : NULL; + const char *arg_vni = carg_vni ? carg_vni->arg : NULL; + const char *arg_rd = carg_rd ? carg_rd->arg : NULL; + return parse_deleter_args (vty, bgp,arg_prefix, arg_vn, arg_un, + arg_l2addr, arg_vni, arg_rd, + arg_rfg, rcdarg); } static void @@ -3271,51 +3319,37 @@ clear_vnc_responses (struct rfapi_local_reg_delete_arg *cda) * TBD need to count deleted prefixes and nves? * * ENXIO BGP or VNC not configured - */ + */ static int -rfapiDeleteLocalPrefixes (struct rfapi_local_reg_delete_arg *cda) +rfapiDeleteLocalPrefixesByRFD (struct rfapi_local_reg_delete_arg *cda, + struct rfapi_descriptor *rfd) { - struct rfapi_ip_addr *pUn; /* NULL = wildcard */ - struct rfapi_ip_addr *pVn; /* NULL = wildcard */ - struct prefix *pPrefix; /* NULL = wildcard */ + struct rfapi_ip_addr *pUn; /* NULL = wildcard */ + struct rfapi_ip_addr *pVn; /* NULL = wildcard */ + struct prefix *pPrefix; /* NULL = wildcard */ + struct prefix_rd *pPrd; /* NULL = wildcard */ - struct rfapi *h; - struct listnode *node; - struct rfapi_descriptor *rfd; struct rfapi_ip_prefix rprefix; - struct bgp *bgp_default = bgp_get_default (); struct rfapi_next_hop_entry *head = NULL; struct rfapi_next_hop_entry *tail = NULL; - struct rfapi_cfg *rfapi_cfg; #if DEBUG_L2_EXTRA - vnc_zlog_debug_verbose ("%s: entry", __func__); + vnc_zlog_debug_verbose ("%s: entry", __func__); #endif - if (!bgp_default) - return ENXIO; - - pUn = (cda->un_address.addr_family ? &cda->un_address : NULL); - pVn = (cda->vn_address.addr_family ? &cda->vn_address : NULL); - pPrefix = (cda->prefix.family ? &cda->prefix : NULL); - - h = bgp_default->rfapi; - rfapi_cfg = bgp_default->rfapi_cfg; - - if (!h || !rfapi_cfg) - return ENXIO; + pUn = (cda->un_address.addr_family ? &cda->un_address : NULL); + pVn = (cda->vn_address.addr_family ? &cda->vn_address : NULL); + pPrefix = (cda->prefix.family ? &cda->prefix : NULL); + pPrd = (cda->rd.prefixlen == 64 ? &cda->rd : NULL); if (pPrefix) { rfapiQprefix2Rprefix (pPrefix, &rprefix); } -#if DEBUG_L2_EXTRA - vnc_zlog_debug_verbose ("%s: starting descriptor loop", __func__); -#endif - - for (ALL_LIST_ELEMENTS_RO (&h->descriptors, node, rfd)) + do /* to preserve old code structure */ { + struct rfapi *h=cda->bgp->rfapi;; struct rfapi_adb *adb; int rc; int deleted_from_this_nve; @@ -3375,7 +3409,7 @@ rfapiDeleteLocalPrefixes (struct rfapi_local_reg_delete_arg *cda) if (pPrefix) { - if (!prefix_same (pPrefix, &adb->prefix_ip)) + if (!prefix_same (pPrefix, &adb->u.s.prefix_ip)) { #if DEBUG_L2_EXTRA vnc_zlog_debug_verbose ("%s: adb=%p, prefix doesn't match, skipping", @@ -3384,11 +3418,22 @@ rfapiDeleteLocalPrefixes (struct rfapi_local_reg_delete_arg *cda) continue; } } + if (pPrd) + { + if (memcmp(pPrd->val, adb->u.s.prd.val, 8) != 0) + { +#if DEBUG_L2_EXTRA + vnc_zlog_debug_verbose ("%s: adb=%p, RD doesn't match, skipping", + __func__, adb); +#endif + continue; + } + } if (CHECK_FLAG (cda->l2o.flags, RFAPI_L2O_MACADDR)) { if (memcmp (cda->l2o.o.macaddr.octet, - adb->prefix_eth.u.prefix_eth.octet, ETHER_ADDR_LEN)) + adb->u.s.prefix_eth.u.prefix_eth.octet, ETHER_ADDR_LEN)) { #if DEBUG_L2_EXTRA vnc_zlog_debug_verbose ("%s: adb=%p, macaddr doesn't match, skipping", @@ -3422,48 +3467,43 @@ rfapiDeleteLocalPrefixes (struct rfapi_local_reg_delete_arg *cda) for (ALL_LIST_ELEMENTS_RO (adb_delete_list, node, adb)) { - - struct rfapi_vn_option vn1; - struct rfapi_vn_option vn2; - struct rfapi_vn_option *pVn; int this_advertisement_prefix_count; + struct rfapi_vn_option optary[3]; + struct rfapi_vn_option *opt = NULL; + int cur_opt = 0; this_advertisement_prefix_count = 1; - rfapiQprefix2Rprefix (&adb->prefix_ip, &rp); + rfapiQprefix2Rprefix (&adb->u.s.prefix_ip, &rp); + + memset (optary, 0, sizeof (optary)); /* if mac addr present in advert, make l2o vn option */ - if (adb->prefix_eth.family == AF_ETHERNET) + if (adb->u.s.prefix_eth.family == AF_ETHERNET) { - - memset (&vn1, 0, sizeof (vn1)); - memset (&vn2, 0, sizeof (vn2)); - - vn1.type = RFAPI_VN_OPTION_TYPE_L2ADDR; - vn1.v.l2addr.macaddr = adb->prefix_eth.u.prefix_eth; - - /* - * use saved RD value instead of trying to invert - * complex L2-style RD computation in rfapi_register() - */ - vn2.type = RFAPI_VN_OPTION_TYPE_INTERNAL_RD; - vn2.v.internal_rd = adb->prd; - - vn1.next = &vn2; - - pVn = &vn1; + if (opt != NULL) + opt->next = &optary[cur_opt]; + opt = &optary[cur_opt++]; + opt->type = RFAPI_VN_OPTION_TYPE_L2ADDR; + opt->v.l2addr.macaddr = adb->u.s.prefix_eth.u.prefix_eth; ++this_advertisement_prefix_count; } - else - { - pVn = NULL; - } + /* + * use saved RD value instead of trying to invert + * complex RD computation in rfapi_register() + */ + if (opt != NULL) + opt->next = &optary[cur_opt]; + opt = &optary[cur_opt++]; + opt->type = RFAPI_VN_OPTION_TYPE_INTERNAL_RD; + opt->v.internal_rd = adb->u.s.prd; #if DEBUG_L2_EXTRA vnc_zlog_debug_verbose ("%s: ipN killing reg from adb %p ", __func__, adb); #endif - rc = rfapi_register (rfd, &rp, 0, NULL, pVn, RFAPI_REGISTER_KILL); + rc = rfapi_register (rfd, &rp, 0, NULL, + (cur_opt ? optary : NULL), RFAPI_REGISTER_KILL); if (!rc) { cda->pfx_count += this_advertisement_prefix_count; @@ -3499,7 +3539,7 @@ rfapiDeleteLocalPrefixes (struct rfapi_local_reg_delete_arg *cda) if (CHECK_FLAG (cda->l2o.flags, RFAPI_L2O_MACADDR)) { if (memcmp (cda->l2o.o.macaddr.octet, - adb->prefix_eth.u.prefix_eth.octet, + adb->u.s.prefix_eth.u.prefix_eth.octet, ETHER_ADDR_LEN)) { @@ -3526,7 +3566,7 @@ rfapiDeleteLocalPrefixes (struct rfapi_local_reg_delete_arg *cda) struct rfapi_vn_option vn; - rfapiQprefix2Rprefix (&adb->prefix_ip, &rp); + rfapiQprefix2Rprefix (&adb->u.s.prefix_ip, &rp); memset (&vn, 0, sizeof (vn)); vn.type = RFAPI_VN_OPTION_TYPE_L2ADDR; @@ -3589,11 +3629,44 @@ rfapiDeleteLocalPrefixes (struct rfapi_local_reg_delete_arg *cda) skiplist_insert (cda->nves, hap, hap); } } - } + } while (0); /* to preserve old code structure */ return 0; } +static int +rfapiDeleteLocalPrefixes (struct rfapi_local_reg_delete_arg *cda) +{ + int rc = 0; + + if (cda->rfg) + { + if (cda->rfg->rfd) /* if not open, nothing to delete */ + rc = rfapiDeleteLocalPrefixesByRFD (cda, cda->rfg->rfd); + } + else + { + struct bgp *bgp = cda->bgp; + struct rfapi *h; + struct rfapi_cfg *rfapi_cfg; + + struct listnode *node; + struct rfapi_descriptor *rfd; + if (!bgp) + return ENXIO; + h = bgp->rfapi; + rfapi_cfg = bgp->rfapi_cfg; + if (!h || !rfapi_cfg) + return ENXIO; + vnc_zlog_debug_verbose ("%s: starting descriptor loop", __func__); + for (ALL_LIST_ELEMENTS_RO (&h->descriptors, node, rfd)) + { + rc = rfapiDeleteLocalPrefixesByRFD (cda, rfd); + } + } + return rc; +} + /* * clear_vnc_prefix * @@ -3609,6 +3682,8 @@ clear_vnc_prefix (struct rfapi_local_reg_delete_arg *cda) struct prefix *pVN = NULL; struct prefix *pPrefix = NULL; + struct rfapi_import_table *it = NULL; + /* * Delete matching remote prefixes in holddown */ @@ -3626,7 +3701,11 @@ clear_vnc_prefix (struct rfapi_local_reg_delete_arg *cda) { pPrefix = &cda->prefix; } - rfapiDeleteRemotePrefixes (pUN, pVN, pPrefix, + if (cda->rfg) + { + it = cda->rfg->rfapi_import_table; + } + rfapiDeleteRemotePrefixes (pUN, pVN, pPrefix, it, 0, 1, &cda->remote_active_pfx_count, &cda->remote_active_nve_count, &cda->remote_holddown_pfx_count, @@ -3711,7 +3790,7 @@ DEFUN (clear_vnc_nve_all, struct rfapi_local_reg_delete_arg cda; int rc; - if ((rc = parse_deleter_args (vty, NULL, NULL, NULL, NULL, NULL, &cda))) + if ((rc = parse_deleter_args (vty, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &cda))) return rc; cda.vty = vty; @@ -3744,7 +3823,7 @@ DEFUN (clear_vnc_nve_vn_un, int rc; if ((rc = - parse_deleter_args (vty, NULL, argv[4], argv[6], NULL, NULL, &cda))) + parse_deleter_tokens (vty, NULL, NULL, argv[4], argv[6], NULL, NULL, NULL, NULL, &cda))) return rc; cda.vty = vty; @@ -3777,7 +3856,7 @@ DEFUN (clear_vnc_nve_un_vn, int rc; if ((rc = - parse_deleter_args (vty, NULL, argv[6], argv[4], NULL, NULL, &cda))) + parse_deleter_tokens (vty, NULL, NULL, argv[6], argv[4], NULL, NULL, NULL, NULL, &cda))) return rc; cda.vty = vty; @@ -3805,7 +3884,7 @@ DEFUN (clear_vnc_nve_vn, struct rfapi_local_reg_delete_arg cda; int rc; - if ((rc = parse_deleter_args (vty, NULL, argv[4], NULL, NULL, NULL, &cda))) + if ((rc = parse_deleter_tokens (vty, NULL, NULL, argv[4], NULL, NULL, NULL, NULL, NULL, &cda))) return rc; cda.vty = vty; @@ -3832,7 +3911,7 @@ DEFUN (clear_vnc_nve_un, struct rfapi_local_reg_delete_arg cda; int rc; - if ((rc = parse_deleter_args (vty, NULL, NULL, argv[6], NULL, NULL, &cda))) + if ((rc = parse_deleter_tokens (vty, NULL, NULL, NULL, argv[6], NULL, NULL, NULL, NULL, &cda))) return rc; cda.vty = vty; @@ -3875,7 +3954,7 @@ DEFUN (clear_vnc_prefix_vn_un, int rc; if ((rc = - parse_deleter_args (vty, argv[3], argv[5], argv[7], NULL, NULL, &cda))) + parse_deleter_tokens (vty, NULL, argv[3], argv[5], argv[7], NULL, NULL, NULL, NULL, &cda))) return rc; cda.vty = vty; clear_vnc_prefix (&cda); @@ -3905,7 +3984,7 @@ DEFUN (clear_vnc_prefix_un_vn, int rc; if ((rc = - parse_deleter_args (vty, argv[3], argv[7], argv[5], NULL, NULL, &cda))) + parse_deleter_tokens (vty, NULL, argv[3], argv[7], argv[5], NULL, NULL, NULL, NULL, &cda))) return rc; cda.vty = vty; clear_vnc_prefix (&cda); @@ -3931,7 +4010,7 @@ DEFUN (clear_vnc_prefix_un, int rc; if ((rc = - parse_deleter_args (vty, argv[3], NULL, argv[5], NULL, NULL, &cda))) + parse_deleter_tokens (vty, NULL, argv[3], NULL, argv[5], NULL, NULL, NULL, NULL, &cda))) return rc; cda.vty = vty; clear_vnc_prefix (&cda); @@ -3957,7 +4036,7 @@ DEFUN (clear_vnc_prefix_vn, int rc; if ((rc = - parse_deleter_args (vty, argv[3], argv[5], NULL, NULL, NULL, &cda))) + parse_deleter_tokens (vty, NULL, argv[3], argv[5], NULL, NULL, NULL, NULL, NULL, &cda))) return rc; cda.vty = vty; clear_vnc_prefix (&cda); @@ -3979,7 +4058,7 @@ DEFUN (clear_vnc_prefix_all, struct rfapi_local_reg_delete_arg cda; int rc; - if ((rc = parse_deleter_args (vty, argv[3], NULL, NULL, NULL, NULL, &cda))) + if ((rc = parse_deleter_tokens (vty, NULL, argv[3], NULL, NULL, NULL, NULL, NULL, NULL, &cda))) return rc; cda.vty = vty; clear_vnc_prefix (&cda); @@ -4021,8 +4100,8 @@ DEFUN (clear_vnc_mac_vn_un, /* pfx vn un L2 VNI */ if ((rc = - parse_deleter_args (vty, NULL, argv[7], argv[9], argv[3], argv[5], - &cda))) + parse_deleter_tokens (vty, NULL, NULL, argv[7], argv[9], argv[3], argv[5], + NULL, NULL, &cda))) return rc; cda.vty = vty; clear_vnc_prefix (&cda); @@ -4055,8 +4134,8 @@ DEFUN (clear_vnc_mac_un_vn, /* pfx vn un L2 VNI */ if ((rc = - parse_deleter_args (vty, NULL, argv[9], argv[7], argv[3], argv[5], - &cda))) + parse_deleter_tokens (vty, NULL, NULL, argv[9], argv[7], argv[3], argv[5], + NULL, NULL, &cda))) return rc; cda.vty = vty; clear_vnc_prefix (&cda); @@ -4085,7 +4164,7 @@ DEFUN (clear_vnc_mac_un, /* pfx vn un L2 VNI */ if ((rc = - parse_deleter_args (vty, NULL, NULL, argv[7], argv[3], argv[5], &cda))) + parse_deleter_tokens (vty, NULL, NULL, NULL, argv[7], argv[3], argv[5], NULL, NULL, &cda))) return rc; cda.vty = vty; clear_vnc_prefix (&cda); @@ -4114,7 +4193,7 @@ DEFUN (clear_vnc_mac_vn, /* pfx vn un L2 VNI */ if ((rc = - parse_deleter_args (vty, NULL, argv[7], NULL, argv[3], argv[5], &cda))) + parse_deleter_tokens (vty, NULL, NULL, argv[7], NULL, argv[3], argv[5], NULL, NULL, &cda))) return rc; cda.vty = vty; clear_vnc_prefix (&cda); @@ -4140,7 +4219,7 @@ DEFUN (clear_vnc_mac_all, /* pfx vn un L2 VNI */ if ((rc = - parse_deleter_args (vty, NULL, NULL, NULL, argv[3], argv[5], &cda))) + parse_deleter_tokens (vty, NULL, NULL, NULL, NULL, argv[3], argv[5], NULL, NULL, &cda))) return rc; cda.vty = vty; clear_vnc_prefix (&cda); @@ -4181,8 +4260,8 @@ DEFUN (clear_vnc_mac_vn_un_prefix, /* pfx vn un L2 VNI */ if ((rc = - parse_deleter_args (vty, argv[11], argv[7], argv[9], argv[3], argv[5], - &cda))) + parse_deleter_tokens (vty, NULL, argv[11], argv[7], argv[9], argv[3], argv[5], + NULL, NULL, &cda))) return rc; cda.vty = vty; clear_vnc_prefix (&cda); @@ -4223,8 +4302,8 @@ DEFUN (clear_vnc_mac_un_vn_prefix, /* pfx vn un L2 VNI */ if ((rc = - parse_deleter_args (vty, argv[11], argv[9], argv[7], argv[3], argv[5], - &cda))) + parse_deleter_tokens (vty, NULL, argv[11], argv[9], argv[7], argv[3], argv[5], + NULL, NULL, &cda))) return rc; cda.vty = vty; clear_vnc_prefix (&cda); @@ -4257,8 +4336,8 @@ DEFUN (clear_vnc_mac_un_prefix, /* pfx vn un L2 VNI */ if ((rc = - parse_deleter_args (vty, argv[9], NULL, argv[7], argv[3], argv[5], - &cda))) + parse_deleter_tokens (vty, NULL, argv[9], NULL, argv[7], argv[3], argv[5], + NULL, NULL, &cda))) return rc; cda.vty = vty; clear_vnc_prefix (&cda); @@ -4291,8 +4370,8 @@ DEFUN (clear_vnc_mac_vn_prefix, /* pfx vn un L2 VNI */ if ((rc = - parse_deleter_args (vty, argv[9], argv[7], NULL, argv[3], argv[5], - &cda))) + parse_deleter_tokens (vty, NULL, argv[9], argv[7], NULL, argv[3], argv[5], + NULL, NULL, &cda))) return rc; cda.vty = vty; clear_vnc_prefix (&cda); @@ -4321,7 +4400,7 @@ DEFUN (clear_vnc_mac_all_prefix, /* pfx vn un L2 VNI */ if ((rc = - parse_deleter_args (vty, argv[7], NULL, NULL, argv[3], argv[5], &cda))) + parse_deleter_tokens (vty, NULL, argv[7], NULL, NULL, argv[3], argv[5], NULL, NULL, &cda))) return rc; cda.vty = vty; clear_vnc_prefix (&cda); @@ -4929,6 +5008,361 @@ notcfg: return CMD_WARNING; } +/************************************************************************ + * Add prefix with vrf + * + * add [vrf <vrf-name>] prefix <prefix> + * [rd <value>] [label <value>] [local-preference <0-4294967295>] + ************************************************************************/ +static int +vnc_add_vrf_prefix (struct vty *vty, + const char *arg_vrf, + const char *arg_prefix, + const char *arg_rd, /* optional */ + const char *arg_label, /* optional */ + const char *arg_pref) /* optional */ +{ + struct bgp *bgp; + struct rfapi_nve_group_cfg *rfg; + struct prefix pfx; + struct rfapi_ip_prefix rpfx; + uint32_t pref = 0; + struct rfapi_vn_option optary[3]; + struct rfapi_vn_option *opt = NULL; + int cur_opt = 0; + + bgp = bgp_get_default (); /* assume main instance for now */ + if (!bgp) + { + vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE); + return CMD_WARNING; + } + if (!bgp->rfapi || !bgp->rfapi_cfg) + { + vty_out (vty, "VRF support not configured%s", VTY_NEWLINE); + return CMD_WARNING; + } + + rfg = bgp_rfapi_cfg_match_byname (bgp, arg_vrf, RFAPI_GROUP_CFG_VRF); + /* arg checks */ + if (!rfg) + { + vty_out (vty, "VRF \"%s\" appears not to be configured.%s", + arg_vrf, VTY_NEWLINE); + return CMD_WARNING; + } + if (!rfg->rt_export_list || !rfg->rfapi_import_table) + { + vty_out (vty, "VRF \"%s\" is missing RT import/export RT configuration.%s", + arg_vrf, VTY_NEWLINE); + return CMD_WARNING; + } + if (!rfg->rd.family && !arg_rd) + { + vty_out (vty, "VRF \"%s\" isn't configured with an RD, so RD must be provided.%s", + arg_vrf, VTY_NEWLINE); + return CMD_WARNING; + } + if (rfg->label > MPLS_LABEL_MAX && !arg_label) + { + vty_out (vty, "VRF \"%s\" isn't configured with a default labels, so a label must be provided.%s", + arg_vrf, VTY_NEWLINE); + return CMD_WARNING; + } + if (!str2prefix (arg_prefix, &pfx)) + { + vty_out (vty, "Malformed prefix \"%s\"%s", + arg_prefix, VTY_NEWLINE); + return CMD_WARNING; + } + rfapiQprefix2Rprefix (&pfx, &rpfx); + memset (optary, 0, sizeof (optary)); + if (arg_rd) + { + if (opt != NULL) + opt->next = &optary[cur_opt]; + opt = &optary[cur_opt++]; + opt->type = RFAPI_VN_OPTION_TYPE_INTERNAL_RD; + if (!str2prefix_rd (arg_rd, &opt->v.internal_rd)) + { + vty_out (vty, "Malformed RD \"%s\"%s", + arg_rd, VTY_NEWLINE); + return CMD_WARNING; + } + } + if (rfg->label <= MPLS_LABEL_MAX || arg_label) + { + struct rfapi_l2address_option *l2o; + if (opt != NULL) + opt->next = &optary[cur_opt]; + opt = &optary[cur_opt++]; + opt->type = RFAPI_VN_OPTION_TYPE_L2ADDR; + l2o = &opt->v.l2addr; + if (arg_label) + { + int32_t label; + VTY_GET_INTEGER_RANGE ("Label value", label, arg_label, 0, MPLS_LABEL_MAX); + l2o->label = label; + } + else + l2o->label = rfg->label; + } + if (arg_pref) + { + char *endptr = NULL; + pref = strtoul (arg_pref, &endptr, 10); + if (*endptr != '\0') + { + vty_out (vty, "%% Invalid local-preference value \"%s\"%s", arg_pref, VTY_NEWLINE); + return CMD_WARNING; + } + } + rpfx.cost = 255 - (pref & 255) ; + if (rfg->rfd == NULL) /* need new rfapi_handle */ + { + /* based on rfapi_open */ + struct rfapi_descriptor *rfd; + rfd = XCALLOC (MTYPE_RFAPI_DESC, sizeof (struct rfapi_descriptor)); + rfd->bgp = bgp; + rfg->rfd = rfd; + /* leave most fields empty as will get from (dynamic) config when needed */ + rfd->default_tunneltype_option.type = BGP_ENCAP_TYPE_MPLS; + rfd->cookie = rfg; + if (rfg->vn_prefix.family && + !CHECK_FLAG(rfg->flags, RFAPI_RFG_VPN_NH_SELF)) + { + rfapiQprefix2Raddr(&rfg->vn_prefix, &rfd->vn_addr); + } + else + { + memset(&rfd->vn_addr, 0, sizeof(struct rfapi_ip_addr)); + rfd->vn_addr.addr_family = AF_INET; + rfd->vn_addr.addr.v4 = bgp->router_id; + } + rfd->un_addr = rfd->vn_addr; /* sigh, need something in UN for lookups */ + vnc_zlog_debug_verbose ("%s: Opening RFD for VRF %s", + __func__, rfg->name); + rfapi_init_and_open(bgp, rfd, rfg); + } + + if (!rfapi_register (rfg->rfd, &rpfx, RFAPI_INFINITE_LIFETIME, NULL, + (cur_opt ? optary : NULL), RFAPI_REGISTER_ADD)) + { + struct rfapi_next_hop_entry *head = NULL; + struct rfapi_next_hop_entry *tail = NULL; + struct rfapi_vn_option *vn_opt_new; + + vnc_zlog_debug_verbose ("%s: rfapi_register succeeded", __func__); + + if (bgp->rfapi->rfp_methods.local_cb) + { + struct rfapi_descriptor *r = (struct rfapi_descriptor *) rfg->rfd; + vn_opt_new = rfapi_vn_options_dup (opt); + + rfapiAddDeleteLocalRfpPrefix (&r->un_addr, &r->vn_addr, &rpfx, + 1, RFAPI_INFINITE_LIFETIME, + vn_opt_new, &head, &tail); + if (head) + { + bgp->rfapi->flags |= RFAPI_INCALLBACK; + (*bgp->rfapi->rfp_methods.local_cb) (head, r->cookie); + bgp->rfapi->flags &= ~RFAPI_INCALLBACK; + } + head = tail = NULL; + } + vnc_zlog_debug_verbose ("%s completed, count=%d/%d", __func__, + rfg->rfapi_import_table->local_count[AFI_IP], + rfg->rfapi_import_table->local_count[AFI_IP6]); + return CMD_SUCCESS; + } + + vnc_zlog_debug_verbose ("%s: rfapi_register failed", __func__); + vty_out (vty, "Add failed.%s", VTY_NEWLINE); + return CMD_WARNING; +} + +DEFUN (add_vrf_prefix_rd_label_pref, + add_vrf_prefix_rd_label_pref_cmd, + "add vrf NAME prefix <A.B.C.D/M|X:X::X:X/M> [rd ASN:nn_or_IP-address] [label (0-1048575)] [preference (0-4294967295)]", + "Add\n" + "To a VRF\n" + "VRF name\n" + "Add/modify prefix related information\n" + "IPv4 prefix\n" + "IPv6 prefix\n" + "Override configured VRF Route Distinguisher\n" + "<as-number>:<number> or <ip-address>:<number>\n" + "Override configured VRF label" + "Label Value <0-1048575>\n" + "Set advertised local preference\n" + "local preference (higher=more preferred)\n") +{ + char *arg_vrf = argv[2]->arg; + char *arg_prefix = argv[4]->arg; + char *arg_rd = NULL; /* optional */ + char *arg_label = NULL; /* optional */ + char *arg_pref = NULL; /* optional */ + int pargc = 5; + argc--; /* don't parse argument */ + while (pargc < argc) + { + switch (argv[pargc++]->arg[0]) + { + case 'r': + arg_rd = argv[pargc]->arg; + break; + case 'l': + arg_label = argv[pargc]->arg; + break; + case 'p': + arg_pref = argv[pargc]->arg; + break; + default: + break; + } + pargc ++; + } + + return vnc_add_vrf_prefix (vty, arg_vrf, arg_prefix, arg_rd, arg_label, arg_pref); +} + +/************************************************************************ + * del prefix with vrf + * + * clear [vrf <vrf-name>] prefix <prefix> [rd <value>] + ************************************************************************/ +static int +rfapi_cfg_group_it_count(struct rfapi_nve_group_cfg *rfg) +{ + int count = 0; + afi_t afi = AFI_MAX; + while (afi-- > 0) + { + count += rfg->rfapi_import_table->local_count[afi]; + } + return count; +} + +static void +clear_vnc_vrf_closer (struct rfapi_nve_group_cfg *rfg) +{ + struct rfapi_descriptor *rfd = rfg->rfd; + afi_t afi; + + if (rfd == NULL) + return; + /* check if IT is empty */ + for (afi = 0; + afi < AFI_MAX && rfg->rfapi_import_table->local_count[afi] == 0; + afi++); + + if (afi == AFI_MAX) + { + vnc_zlog_debug_verbose ("%s: closing RFD for VRF %s", + __func__, rfg->name); + rfg->rfd = NULL; + rfapi_close(rfd); + } + else + { + vnc_zlog_debug_verbose ("%s: VRF %s afi=%d count=%d", + __func__, rfg->name, afi, + rfg->rfapi_import_table->local_count[afi]); + } +} + +static int +vnc_clear_vrf (struct vty *vty, + struct bgp *bgp, + const char *arg_vrf, + const char *arg_prefix, /* NULL = all */ + const char *arg_rd) /* optional */ +{ + struct rfapi_nve_group_cfg *rfg; + struct rfapi_local_reg_delete_arg cda; + int rc; + int start_count; + + if (bgp == NULL) + bgp = bgp_get_default (); /* assume main instance for now */ + if (!bgp) + { + vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE); + return CMD_WARNING; + } + if (!bgp->rfapi || !bgp->rfapi_cfg) + { + vty_out (vty, "VRF support not configured%s", VTY_NEWLINE); + return CMD_WARNING; + } + rfg = bgp_rfapi_cfg_match_byname (bgp, arg_vrf, RFAPI_GROUP_CFG_VRF); + /* arg checks */ + if (!rfg) + { + vty_out (vty, "VRF \"%s\" appears not to be configured.%s", + arg_vrf, VTY_NEWLINE); + return CMD_WARNING; + } + rc = parse_deleter_args (vty, bgp, arg_prefix, NULL, NULL, NULL, NULL, + arg_rd, rfg, &cda); + if (rc != CMD_SUCCESS) /* parse error */ + return rc; + + start_count = rfapi_cfg_group_it_count(rfg); + clear_vnc_prefix (&cda); + clear_vnc_vrf_closer (rfg); + vty_out (vty, "Cleared %u out of %d prefixes.%s", + cda.pfx_count, start_count, VTY_NEWLINE); + return CMD_SUCCESS; +} + +DEFUN (clear_vrf_prefix_rd, + clear_vrf_prefix_rd_cmd, + "clear vrf NAME [prefix <A.B.C.D/M|X:X::X:X/M>] [rd ASN:nn_or_IP-address]", + "Clear stored data\n" + "From a VRF\n" + "VRF name\n" + "Prefix related information\n" + "IPv4 prefix\n" + "IPv6 prefix\n" + "Specific VRF Route Distinguisher\n" + "<as-number>:<number> or <ip-address>:<number>\n") +{ + char *arg_vrf = argv[2]->arg; + char *arg_prefix = NULL; /* optional */ + char *arg_rd = NULL; /* optional */ + int pargc = 3; + argc--; /* don't check parameter */ + while (pargc < argc) + { + switch (argv[pargc++]->arg[0]) + { + case 'r': + arg_rd = argv[pargc]->arg; + break; + case 'p': + arg_prefix = argv[pargc]->arg; + break; + default: + break; + } + pargc ++; + } + return vnc_clear_vrf (vty, NULL, arg_vrf, arg_prefix, arg_rd); +} + +DEFUN (clear_vrf_all, + clear_vrf_all_cmd, + "clear vrf NAME all", + "Clear stored data\n" + "From a VRF\n" + "VRF name\n" + "All prefixes\n") +{ + char *arg_vrf = argv[2]->arg; + return vnc_clear_vrf (vty, NULL, arg_vrf, NULL, NULL); +} + void rfapi_vty_init () { install_element (ENABLE_NODE, &add_vnc_prefix_cost_life_lnh_cmd); @@ -4952,6 +5386,8 @@ void rfapi_vty_init () install_element (ENABLE_NODE, &add_vnc_mac_vni_life_cmd); install_element (ENABLE_NODE, &add_vnc_mac_vni_cmd); + install_element (ENABLE_NODE, &add_vrf_prefix_rd_label_pref_cmd); + install_element (ENABLE_NODE, &clear_vnc_nve_all_cmd); install_element (ENABLE_NODE, &clear_vnc_nve_vn_un_cmd); install_element (ENABLE_NODE, &clear_vnc_nve_un_vn_cmd); @@ -4976,6 +5412,9 @@ void rfapi_vty_init () install_element (ENABLE_NODE, &clear_vnc_mac_vn_prefix_cmd); install_element (ENABLE_NODE, &clear_vnc_mac_all_prefix_cmd); + install_element (ENABLE_NODE, &clear_vrf_prefix_rd_cmd); + install_element (ENABLE_NODE, &clear_vrf_all_cmd); + install_element (ENABLE_NODE, &vnc_clear_counters_cmd); install_element (VIEW_NODE, &vnc_show_summary_cmd); diff --git a/lib/command.c b/lib/command.c index f75a924fb..9485beddd 100644 --- a/lib/command.c +++ b/lib/command.c @@ -748,6 +748,7 @@ node_parent ( enum node_type node ) case BGP_VPNV6_NODE: case BGP_ENCAP_NODE: case BGP_ENCAPV6_NODE: + case BGP_VRF_POLICY_NODE: case BGP_VNC_DEFAULTS_NODE: case BGP_VNC_NVE_GROUP_NODE: case BGP_VNC_L2_GROUP_NODE: @@ -1113,6 +1114,7 @@ cmd_exit (struct vty *vty) case BGP_VPNV6_NODE: case BGP_ENCAP_NODE: case BGP_ENCAPV6_NODE: + case BGP_VRF_POLICY_NODE: case BGP_VNC_DEFAULTS_NODE: case BGP_VNC_NVE_GROUP_NODE: case BGP_VNC_L2_GROUP_NODE: @@ -1176,6 +1178,7 @@ DEFUN (config_end, case BGP_NODE: case BGP_ENCAP_NODE: case BGP_ENCAPV6_NODE: + case BGP_VRF_POLICY_NODE: case BGP_VNC_DEFAULTS_NODE: case BGP_VNC_NVE_GROUP_NODE: case BGP_VNC_L2_GROUP_NODE: diff --git a/lib/command.h b/lib/command.h index ff1b1a0e8..3c3c3ae37 100644 --- a/lib/command.h +++ b/lib/command.h @@ -100,6 +100,7 @@ enum node_type BGP_IPV6M_NODE, /* BGP IPv6 multicast address family. */ BGP_ENCAP_NODE, /* BGP ENCAP SAFI */ BGP_ENCAPV6_NODE, /* BGP ENCAP SAFI */ + BGP_VRF_POLICY_NODE, /* BGP VRF policy */ BGP_VNC_DEFAULTS_NODE, /* BGP VNC nve defaults */ BGP_VNC_NVE_GROUP_NODE, /* BGP VNC nve group */ BGP_VNC_L2_GROUP_NODE, /* BGP VNC L2 group */ @@ -742,6 +742,7 @@ vty_end_config (struct vty *vty) case BGP_VPNV6_NODE: case BGP_ENCAP_NODE: case BGP_ENCAPV6_NODE: + case BGP_VRF_POLICY_NODE: case BGP_VNC_DEFAULTS_NODE: case BGP_VNC_NVE_GROUP_NODE: case BGP_VNC_L2_GROUP_NODE: diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index 50677b568..51b5091c5 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -312,6 +312,10 @@ vtysh_execute_func (const char *line, int pager) { vtysh_execute("exit-address-family"); } + else if (saved_node == BGP_VRF_POLICY_NODE && (tried == 1)) + { + vtysh_execute("exit-vrf-policy"); + } else if ((saved_node == BGP_VNC_DEFAULTS_NODE || saved_node == BGP_VNC_NVE_GROUP_NODE || saved_node == BGP_VNC_L2_GROUP_NODE) && (tried == 1)) @@ -963,6 +967,11 @@ static struct cmd_node bgp_vnc_nve_group_node = "%s(config-router-vnc-nve-group)# " }; +static struct cmd_node bgp_vrf_policy_node = { + BGP_VRF_POLICY_NODE, + "%s(config-router-vrf-policy)# " +}; + static struct cmd_node bgp_vnc_l2_group_node = { BGP_VNC_L2_GROUP_NODE, @@ -1210,6 +1219,17 @@ DEFUNSH (VTYSH_BGPD, } DEFUNSH (VTYSH_BGPD, + vnc_vrf_policy, + vnc_vrf_policy_cmd, + "vrf-policy NAME", + "Configure a VRF policy group\n" + "Group name\n") +{ + vty->node = BGP_VRF_POLICY_NODE; + return CMD_SUCCESS; +} + +DEFUNSH (VTYSH_BGPD, vnc_l2_group, vnc_l2_group_cmd, "vnc l2-group NAME", @@ -1481,6 +1501,7 @@ vtysh_exit (struct vty *vty) case BGP_IPV4M_NODE: case BGP_IPV6_NODE: case BGP_IPV6M_NODE: + case BGP_VRF_POLICY_NODE: case BGP_VNC_DEFAULTS_NODE: case BGP_VNC_NVE_GROUP_NODE: case BGP_VNC_L2_GROUP_NODE: @@ -1560,6 +1581,17 @@ DEFUNSH (VTYSH_BGPD, return CMD_SUCCESS; } +DEFUNSH (VTYSH_BGPD, + exit_vrf_policy, + exit_vrf_policy_cmd, + "exit-vrf-policy", + "Exit from VRF configuration mode\n") +{ + if (vty->node == BGP_VRF_POLICY_NODE) + vty->node = BGP_NODE; + return CMD_SUCCESS; +} + DEFUNSH (VTYSH_RIPD, vtysh_exit_ripd, vtysh_exit_ripd_cmd, @@ -3042,6 +3074,7 @@ vtysh_init_vty (void) install_node (&bgp_ipv4m_node, NULL); install_node (&bgp_ipv6_node, NULL); install_node (&bgp_ipv6m_node, NULL); + install_node (&bgp_vrf_policy_node, NULL); install_node (&bgp_vnc_defaults_node, NULL); install_node (&bgp_vnc_nve_group_node, NULL); install_node (&bgp_vnc_l2_group_node, NULL); @@ -3079,6 +3112,7 @@ vtysh_init_vty (void) vtysh_install_default (BGP_IPV6_NODE); vtysh_install_default (BGP_IPV6M_NODE); #if ENABLE_BGP_VNC + vtysh_install_default (BGP_VRF_POLICY_NODE); vtysh_install_default (BGP_VNC_DEFAULTS_NODE); vtysh_install_default (BGP_VNC_NVE_GROUP_NODE); vtysh_install_default (BGP_VNC_L2_GROUP_NODE); @@ -3150,6 +3184,8 @@ vtysh_init_vty (void) install_element (BGP_IPV6M_NODE, &vtysh_exit_bgpd_cmd); install_element (BGP_IPV6M_NODE, &vtysh_quit_bgpd_cmd); #if defined (ENABLE_BGP_VNC) + install_element (BGP_VRF_POLICY_NODE, &vtysh_exit_bgpd_cmd); + install_element (BGP_VRF_POLICY_NODE, &vtysh_quit_bgpd_cmd); install_element (BGP_VNC_DEFAULTS_NODE, &vtysh_exit_bgpd_cmd); install_element (BGP_VNC_DEFAULTS_NODE, &vtysh_quit_bgpd_cmd); install_element (BGP_VNC_NVE_GROUP_NODE, &vtysh_exit_bgpd_cmd); @@ -3191,6 +3227,7 @@ vtysh_init_vty (void) install_element (BGP_ENCAPV6_NODE, &vtysh_end_all_cmd); install_element (BGP_IPV6_NODE, &vtysh_end_all_cmd); install_element (BGP_IPV6M_NODE, &vtysh_end_all_cmd); + install_element (BGP_VRF_POLICY_NODE, &vtysh_end_all_cmd); install_element (BGP_VNC_DEFAULTS_NODE, &vtysh_end_all_cmd); install_element (BGP_VNC_NVE_GROUP_NODE, &vtysh_end_all_cmd); install_element (BGP_VNC_L2_GROUP_NODE, &vtysh_end_all_cmd); @@ -3239,6 +3276,7 @@ vtysh_init_vty (void) install_element (BGP_NODE, &address_family_encapv4_cmd); install_element (BGP_NODE, &address_family_encapv6_cmd); #if defined(ENABLE_BGP_VNC) + install_element (BGP_NODE, &vnc_vrf_policy_cmd); install_element (BGP_NODE, &vnc_defaults_cmd); install_element (BGP_NODE, &vnc_nve_group_cmd); install_element (BGP_NODE, &vnc_l2_group_cmd); @@ -3256,6 +3294,7 @@ vtysh_init_vty (void) install_element (BGP_IPV6_NODE, &exit_address_family_cmd); install_element (BGP_IPV6M_NODE, &exit_address_family_cmd); + install_element (BGP_VRF_POLICY_NODE, &exit_vrf_policy_cmd); install_element (BGP_VNC_DEFAULTS_NODE, &exit_vnc_config_cmd); install_element (BGP_VNC_NVE_GROUP_NODE, &exit_vnc_config_cmd); install_element (BGP_VNC_L2_GROUP_NODE, &exit_vnc_config_cmd); |