diff options
author | Lou Berger <lberger@labn.net> | 2017-01-12 14:30:17 +0100 |
---|---|---|
committer | Lou Berger <lberger@labn.net> | 2017-01-23 02:54:57 +0100 |
commit | 5ff06872e924383e2139b63e9f6e8344b183c283 (patch) | |
tree | 97bba684f2c64f7dffc6049796e2926e26842859 /bgpd | |
parent | bgpd rfapi: fix issue where advertised prefixes were not being disambiguated (diff) | |
download | frr-5ff06872e924383e2139b63e9f6e8344b183c283.tar.xz frr-5ff06872e924383e2139b63e9f6e8344b183c283.zip |
bgpd: add vrf-policy config using existing vnc code
add add/clear vrf prefix
+ Modified for FRR master parser
Signed-off-by: Lou Berger <lberger@labn.net>
Diffstat (limited to 'bgpd')
-rw-r--r-- | bgpd/bgp_mplsvpn.h | 8 | ||||
-rw-r--r-- | bgpd/rfapi/bgp_rfapi_cfg.c | 778 | ||||
-rw-r--r-- | bgpd/rfapi/bgp_rfapi_cfg.h | 23 | ||||
-rw-r--r-- | bgpd/rfapi/rfapi.c | 97 | ||||
-rw-r--r-- | bgpd/rfapi/rfapi_import.c | 13 | ||||
-rw-r--r-- | bgpd/rfapi/rfapi_import.h | 2 | ||||
-rw-r--r-- | bgpd/rfapi/rfapi_private.h | 14 | ||||
-rw-r--r-- | bgpd/rfapi/rfapi_rib.c | 6 | ||||
-rw-r--r-- | bgpd/rfapi/rfapi_vty.c | 623 |
9 files changed, 1386 insertions, 178 deletions
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/rfapi/bgp_rfapi_cfg.c b/bgpd/rfapi/bgp_rfapi_cfg.c index ab9a24e83..a2b0be3cc 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; @@ -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, @@ -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); + + 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); + + 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 6353f7dac..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, diff --git a/bgpd/rfapi/rfapi_import.c b/bgpd/rfapi/rfapi_import.c index 26325b581..5ba98e55d 100644 --- a/bgpd/rfapi/rfapi_import.c +++ b/bgpd/rfapi/rfapi_import.c @@ -4943,6 +4943,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 +4959,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 +4997,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 +5022,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..51afa0002 100644 --- a/bgpd/rfapi/rfapi_import.h +++ b/bgpd/rfapi/rfapi_import.h @@ -223,6 +223,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 +239,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 00f90e35f..ed83ef1e1 100644 --- a/bgpd/rfapi/rfapi_private.h +++ b/bgpd/rfapi/rfapi_private.h @@ -135,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) ( \ @@ -433,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 3a4a15921..8e5d47415 100644 --- a/bgpd/rfapi/rfapi_rib.c +++ b/bgpd/rfapi/rfapi_rib.c @@ -514,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_vty.c b/bgpd/rfapi/rfapi_vty.c index ed3155307..f8142ed29 100644 --- a/bgpd/rfapi/rfapi_vty.c +++ b/bgpd/rfapi/rfapi_vty.c @@ -3004,9 +3004,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 +3109,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 +3174,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 +3312,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; @@ -3384,6 +3411,17 @@ 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 @@ -3422,47 +3460,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->u.s.prefix_ip, &rp); + memset (optary, 0, sizeof (optary)); + /* if mac addr present in advert, make l2o vn option */ 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->u.s.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->u.s.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; @@ -3588,11 +3622,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 * @@ -3608,6 +3675,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 */ @@ -3625,7 +3694,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, @@ -3710,7 +3783,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; @@ -3743,7 +3816,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; @@ -3776,7 +3849,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; @@ -3804,7 +3877,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; @@ -3831,7 +3904,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; @@ -3874,7 +3947,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); @@ -3904,7 +3977,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); @@ -3930,7 +4003,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); @@ -3956,7 +4029,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); @@ -3978,7 +4051,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); @@ -4020,8 +4093,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); @@ -4054,8 +4127,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); @@ -4084,7 +4157,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); @@ -4113,7 +4186,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); @@ -4139,7 +4212,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); @@ -4180,8 +4253,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); @@ -4222,8 +4295,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); @@ -4256,8 +4329,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); @@ -4290,8 +4363,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); @@ -4320,7 +4393,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); @@ -4928,6 +5001,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); @@ -4951,6 +5379,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); @@ -4975,6 +5405,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); |