summaryrefslogtreecommitdiffstats
path: root/bgpd
diff options
context:
space:
mode:
authorLou Berger <lberger@labn.net>2017-01-12 14:30:17 +0100
committerLou Berger <lberger@labn.net>2017-01-23 02:54:57 +0100
commit5ff06872e924383e2139b63e9f6e8344b183c283 (patch)
tree97bba684f2c64f7dffc6049796e2926e26842859 /bgpd
parentbgpd rfapi: fix issue where advertised prefixes were not being disambiguated (diff)
downloadfrr-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.h8
-rw-r--r--bgpd/rfapi/bgp_rfapi_cfg.c778
-rw-r--r--bgpd/rfapi/bgp_rfapi_cfg.h23
-rw-r--r--bgpd/rfapi/rfapi.c97
-rw-r--r--bgpd/rfapi/rfapi_import.c13
-rw-r--r--bgpd/rfapi/rfapi_import.h2
-rw-r--r--bgpd/rfapi/rfapi_private.h14
-rw-r--r--bgpd/rfapi/rfapi_rib.c6
-rw-r--r--bgpd/rfapi/rfapi_vty.c623
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);