summaryrefslogtreecommitdiff
path: root/zebra/interface.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/interface.c')
-rw-r--r--zebra/interface.c388
1 files changed, 294 insertions, 94 deletions
diff --git a/zebra/interface.c b/zebra/interface.c
index 59563834ef..1ba5e972f8 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -1,22 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Interface function.
* Copyright (C) 1997, 1999 Kunihiro Ishiguro
- *
- * This file is part of GNU Zebra.
- *
- * GNU Zebra is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * GNU Zebra is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; see the file COPYING; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
@@ -33,6 +18,7 @@
#include "log.h"
#include "zclient.h"
#include "vrf.h"
+#include "lib/northbound_cli.h"
#include "zebra/rtadv.h"
#include "zebra_ns.h"
@@ -228,6 +214,7 @@ static int if_zebra_delete_hook(struct interface *ifp)
rtadv_if_fini(zebra_if);
+ zebra_l2_bridge_if_cleanup(ifp);
zebra_evpn_if_cleanup(zebra_if);
zebra_evpn_mac_ifp_del(ifp);
@@ -806,12 +793,12 @@ void if_delete_update(struct interface **pifp)
/* Reset some zebra interface params to default values. */
zif = ifp->info;
if (zif) {
+ zebra_evpn_if_cleanup(zif);
zif->zif_type = ZEBRA_IF_OTHER;
zif->zif_slave_type = ZEBRA_IF_SLAVE_NONE;
memset(&zif->l2info, 0, sizeof(union zebra_l2if_info));
memset(&zif->brslave_info, 0,
sizeof(struct zebra_l2info_brslave));
- zebra_evpn_if_cleanup(zif);
zebra_evpn_mac_ifp_del(ifp);
}
@@ -1889,6 +1876,63 @@ static inline bool if_is_protodown_applicable(struct interface *ifp)
return true;
}
+static void zebra_vxlan_if_vni_dump_vty(struct vty *vty,
+ struct zebra_vxlan_vni *vni)
+{
+ char str[INET6_ADDRSTRLEN];
+
+ vty_out(vty, " VxLAN Id %u", vni->vni);
+ if (vni->access_vlan)
+ vty_out(vty, " Access VLAN Id %u\n", vni->access_vlan);
+
+ if (vni->mcast_grp.s_addr != INADDR_ANY)
+ vty_out(vty, " Mcast Group %s",
+ inet_ntop(AF_INET, &vni->mcast_grp, str, sizeof(str)));
+}
+
+static void zebra_vxlan_if_vni_hash_dump_vty(struct hash_bucket *bucket,
+ void *ctxt)
+{
+ struct vty *vty;
+ struct zebra_vxlan_vni *vni;
+
+ vni = (struct zebra_vxlan_vni *)bucket->data;
+ vty = (struct vty *)ctxt;
+
+ zebra_vxlan_if_vni_dump_vty(vty, vni);
+}
+
+static void zebra_vxlan_if_dump_vty(struct vty *vty, struct zebra_if *zebra_if)
+{
+ struct zebra_l2info_vxlan *vxlan_info;
+ struct zebra_vxlan_vni_info *vni_info;
+
+ vxlan_info = &zebra_if->l2info.vxl;
+ vni_info = &vxlan_info->vni_info;
+
+ if (vxlan_info->vtep_ip.s_addr != INADDR_ANY)
+ vty_out(vty, " VTEP IP: %pI4", &vxlan_info->vtep_ip);
+
+ if (vxlan_info->ifindex_link && (vxlan_info->link_nsid != NS_UNKNOWN)) {
+ struct interface *ifp;
+
+ ifp = if_lookup_by_index_per_ns(
+ zebra_ns_lookup(vxlan_info->link_nsid),
+ vxlan_info->ifindex_link);
+ vty_out(vty, " Link Interface %s",
+ ifp == NULL ? "Unknown" : ifp->name);
+ }
+
+ if (IS_ZEBRA_VXLAN_IF_VNI(zebra_if)) {
+ zebra_vxlan_if_vni_dump_vty(vty, &vni_info->vni);
+ } else {
+ hash_iterate(vni_info->vni_table,
+ zebra_vxlan_if_vni_hash_dump_vty, vty);
+ }
+
+ vty_out(vty, "\n");
+}
+
/* Interface's information print out to vty interface. */
static void if_dump_vty(struct vty *vty, struct interface *ifp)
{
@@ -1997,42 +2041,15 @@ static void if_dump_vty(struct vty *vty, struct interface *ifp)
zebra_zifslavetype_2str(zebra_if->zif_slave_type));
if (IS_ZEBRA_IF_BRIDGE(ifp)) {
- struct zebra_l2info_bridge *bridge_info;
-
- bridge_info = &zebra_if->l2info.br;
vty_out(vty, " Bridge VLAN-aware: %s\n",
- bridge_info->vlan_aware ? "yes" : "no");
+ IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(zebra_if) ? "yes" : "no");
} else if (IS_ZEBRA_IF_VLAN(ifp)) {
struct zebra_l2info_vlan *vlan_info;
vlan_info = &zebra_if->l2info.vl;
vty_out(vty, " VLAN Id %u\n", vlan_info->vid);
} else if (IS_ZEBRA_IF_VXLAN(ifp)) {
- struct zebra_l2info_vxlan *vxlan_info;
-
- vxlan_info = &zebra_if->l2info.vxl;
- vty_out(vty, " VxLAN Id %u", vxlan_info->vni);
- if (vxlan_info->vtep_ip.s_addr != INADDR_ANY)
- vty_out(vty, " VTEP IP: %pI4",
- &vxlan_info->vtep_ip);
- if (vxlan_info->access_vlan)
- vty_out(vty, " Access VLAN Id %u\n",
- vxlan_info->access_vlan);
- if (vxlan_info->mcast_grp.s_addr != INADDR_ANY)
- vty_out(vty, " Mcast Group %pI4",
- &vxlan_info->mcast_grp);
- if (vxlan_info->ifindex_link &&
- (vxlan_info->link_nsid != NS_UNKNOWN)) {
- struct interface *ifp;
-
- ifp = if_lookup_by_index_per_ns(
- zebra_ns_lookup(vxlan_info->link_nsid),
- vxlan_info->ifindex_link);
- vty_out(vty, " Link Interface %s",
- ifp == NULL ? "Unknown" :
- ifp->name);
- }
- vty_out(vty, "\n");
+ zebra_vxlan_if_dump_vty(vty, zebra_if);
} else if (IS_ZEBRA_IF_GRE(ifp)) {
struct zebra_l2info_gre *gre_info;
@@ -2225,6 +2242,59 @@ static void if_dump_vty(struct vty *vty, struct interface *ifp)
#endif /* HAVE_NET_RT_IFLIST */
}
+static void zebra_vxlan_if_vni_dump_vty_json(json_object *json_if,
+ struct zebra_vxlan_vni *vni)
+{
+ json_object_int_add(json_if, "vxlanId", vni->vni);
+ if (vni->access_vlan)
+ json_object_int_add(json_if, "accessVlanId", vni->access_vlan);
+ if (vni->mcast_grp.s_addr != INADDR_ANY)
+ json_object_string_addf(json_if, "mcastGroup", "%pI4",
+ &vni->mcast_grp);
+}
+
+static void zebra_vxlan_if_vni_hash_dump_vty_json(struct hash_bucket *bucket,
+ void *ctxt)
+{
+ json_object *json_if;
+ struct zebra_vxlan_vni *vni;
+
+ vni = (struct zebra_vxlan_vni *)bucket->data;
+ json_if = (json_object *)ctxt;
+
+ zebra_vxlan_if_vni_dump_vty_json(json_if, vni);
+}
+
+static void zebra_vxlan_if_dump_vty_json(json_object *json_if,
+ struct zebra_if *zebra_if)
+{
+ struct zebra_l2info_vxlan *vxlan_info;
+ struct zebra_vxlan_vni_info *vni_info;
+
+ vxlan_info = &zebra_if->l2info.vxl;
+ vni_info = &vxlan_info->vni_info;
+
+ if (vxlan_info->vtep_ip.s_addr != INADDR_ANY)
+ json_object_string_addf(json_if, "vtepIp", "%pI4",
+ &vxlan_info->vtep_ip);
+
+ if (vxlan_info->ifindex_link && (vxlan_info->link_nsid != NS_UNKNOWN)) {
+ struct interface *ifp;
+
+ ifp = if_lookup_by_index_per_ns(
+ zebra_ns_lookup(vxlan_info->link_nsid),
+ vxlan_info->ifindex_link);
+ json_object_string_add(json_if, "linkInterface",
+ ifp == NULL ? "Unknown" : ifp->name);
+ }
+ if (IS_ZEBRA_VXLAN_IF_VNI(zebra_if)) {
+ zebra_vxlan_if_vni_dump_vty_json(json_if, &vni_info->vni);
+ } else {
+ hash_iterate(vni_info->vni_table,
+ zebra_vxlan_if_vni_hash_dump_vty_json, json_if);
+ }
+}
+
static void if_dump_vty_json(struct vty *vty, struct interface *ifp,
json_object *json)
{
@@ -2352,37 +2422,15 @@ static void if_dump_vty_json(struct vty *vty, struct interface *ifp,
bridge_info = &zebra_if->l2info.br;
json_object_boolean_add(json_if, "bridgeVlanAware",
- bridge_info->vlan_aware);
+ bridge_info->bridge.vlan_aware);
} else if (IS_ZEBRA_IF_VLAN(ifp)) {
struct zebra_l2info_vlan *vlan_info;
vlan_info = &zebra_if->l2info.vl;
json_object_int_add(json_if, "vlanId", vlan_info->vid);
} else if (IS_ZEBRA_IF_VXLAN(ifp)) {
- struct zebra_l2info_vxlan *vxlan_info;
-
- vxlan_info = &zebra_if->l2info.vxl;
- json_object_int_add(json_if, "vxlanId", vxlan_info->vni);
- if (vxlan_info->vtep_ip.s_addr != INADDR_ANY)
- json_object_string_addf(json_if, "vtepIp", "%pI4",
- &vxlan_info->vtep_ip);
- if (vxlan_info->access_vlan)
- json_object_int_add(json_if, "accessVlanId",
- vxlan_info->access_vlan);
- if (vxlan_info->mcast_grp.s_addr != INADDR_ANY)
- json_object_string_addf(json_if, "mcastGroup", "%pI4",
- &vxlan_info->mcast_grp);
- if (vxlan_info->ifindex_link
- && (vxlan_info->link_nsid != NS_UNKNOWN)) {
- struct interface *ifp;
+ zebra_vxlan_if_dump_vty_json(json_if, zebra_if);
- ifp = if_lookup_by_index_per_ns(
- zebra_ns_lookup(vxlan_info->link_nsid),
- vxlan_info->ifindex_link);
- json_object_string_add(json_if, "linkInterface",
- ifp == NULL ? "Unknown"
- : ifp->name);
- }
} else if (IS_ZEBRA_IF_GRE(ifp)) {
struct zebra_l2info_gre *gre_info;
@@ -3300,6 +3348,8 @@ DEFUN (no_link_params_enable,
NO_STR
"Disable link parameters on this interface\n")
{
+ char xpath[XPATH_MAXLEN];
+ int ret;
VTY_DECLVAR_CONTEXT(interface, ifp);
if (IS_ZEBRA_DEBUG_EVENT || IS_ZEBRA_DEBUG_MPLS)
@@ -3308,6 +3358,18 @@ DEFUN (no_link_params_enable,
if_link_params_free(ifp);
+ snprintf(
+ xpath, sizeof(xpath),
+ "/frr-interface:lib/interface[name='%s']/frr-zebra:zebra/link-params/affinities",
+ ifp->name);
+ if (yang_dnode_exists(running_config->dnode, xpath))
+ nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
+
+ ret = nb_cli_apply_changes(vty, NULL);
+
+ if (ret != CMD_SUCCESS)
+ return ret;
+
/* force protocols to update LINK STATE due to parameters change */
if (if_is_operative(ifp))
zebra_interface_parameters_update(ifp);
@@ -3473,16 +3535,27 @@ DEFUN (link_params_unrsv_bw,
return CMD_SUCCESS;
}
-DEFUN (link_params_admin_grp,
- link_params_admin_grp_cmd,
- "admin-grp BITPATTERN",
- "Administrative group membership\n"
- "32-bit Hexadecimal value (e.g. 0xa1)\n")
+DEFPY_YANG(link_params_admin_grp, link_params_admin_grp_cmd,
+ "admin-grp BITPATTERN",
+ "Administrative group membership\n"
+ "32-bit Hexadecimal value (e.g. 0xa1)\n")
{
+ char xpath[XPATH_MAXLEN];
int idx_bitpattern = 1;
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct if_link_params *iflp = if_link_params_get(ifp);
unsigned long value;
+ char value_str[11];
+
+ VTY_DECLVAR_CONTEXT(interface, ifp);
+
+ snprintf(
+ xpath, sizeof(xpath),
+ "/frr-interface:lib/interface[name='%s']/frr-zebra:zebra/link-params/affinities",
+ ifp->name);
+ if (yang_dnode_exists(running_config->dnode, xpath)) {
+ vty_out(vty,
+ "cannot use the admin-grp command when affinity is set\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
if (sscanf(argv[idx_bitpattern]->arg, "0x%lx", &value) != 1) {
vty_out(vty, "link_params_admin_grp: fscanf: %s\n",
@@ -3490,27 +3563,29 @@ DEFUN (link_params_admin_grp,
return CMD_WARNING_CONFIG_FAILED;
}
- if (!iflp)
- iflp = if_link_params_enable(ifp);
+ if (value > 0xFFFFFFFF) {
+ vty_out(vty, "value must be not be superior to 0xFFFFFFFF\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
- /* Update Administrative Group if needed */
- link_param_cmd_set_uint32(ifp, &iflp->admin_grp, LP_ADM_GRP, value);
+ snprintf(value_str, sizeof(value_str), "%ld", value);
- return CMD_SUCCESS;
+ nb_cli_enqueue_change(
+ vty, "./frr-zebra:zebra/link-params/legacy-admin-group",
+ NB_OP_MODIFY, value_str);
+
+ return nb_cli_apply_changes(vty, NULL);
}
-DEFUN (no_link_params_admin_grp,
- no_link_params_admin_grp_cmd,
- "no admin-grp",
- NO_STR
- "Disable Administrative group membership on this interface\n")
+DEFPY_YANG(no_link_params_admin_grp, no_link_params_admin_grp_cmd,
+ "no admin-grp",
+ NO_STR "Disable Administrative group membership on this interface\n")
{
- VTY_DECLVAR_CONTEXT(interface, ifp);
+ nb_cli_enqueue_change(
+ vty, "./frr-zebra:zebra/link-params/legacy-admin-group",
+ NB_OP_DESTROY, NULL);
- /* Unset Admin Group */
- link_param_cmd_unset(ifp, LP_ADM_GRP);
-
- return CMD_SUCCESS;
+ return nb_cli_apply_changes(vty, NULL);
}
/* RFC5392 & RFC5316: INTER-AS */
@@ -3927,6 +4002,118 @@ DEFUN (no_link_params_use_bw,
return CMD_SUCCESS;
}
+static int ag_change(struct vty *vty, int argc, struct cmd_token **argv,
+ const char *xpath, bool no, int start_idx)
+{
+ for (int i = start_idx; i < argc; i++)
+ nb_cli_enqueue_change(vty, xpath,
+ no ? NB_OP_DESTROY : NB_OP_CREATE,
+ argv[i]->arg);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/frr-zebra:zebra/link-params/affinities/affinity
+ */
+DEFPY_YANG(link_params_affinity, link_params_affinity_cmd,
+ "[no] affinity NAME...",
+ NO_STR
+ "Interface affinities\n"
+ "Affinity names\n")
+{
+ VTY_DECLVAR_CONTEXT(interface, ifp);
+ char xpath[XPATH_MAXLEN];
+
+ snprintf(
+ xpath, sizeof(xpath),
+ "/frr-interface:lib/interface[name='%s']/frr-zebra:zebra/link-params/legacy-admin-group",
+ ifp->name);
+ if (yang_dnode_exists(running_config->dnode, xpath)) {
+ vty_out(vty,
+ "cannot use the affinity command when admin-grp is set\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ return ag_change(vty, argc, argv,
+ "./frr-zebra:zebra/link-params/affinities/affinity",
+ no, no ? 2 : 1);
+}
+
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/frr-zebra:zebra/link-params/affinities/affinity-mode
+ */
+DEFPY_YANG(link_params_affinity_mode, link_params_affinity_mode_cmd,
+ "affinity-mode <standard|extended|both>$affmode",
+ "Interface affinity mode\n"
+ "Standard Admin-Group only RFC3630,5305,5329 (default)\n"
+ "Extended Admin-Group only RFC7308\n"
+ "Standard and extended Admin-Group format\n")
+{
+ const char *xpath = "./frr-zebra:zebra/link-params/affinity-mode";
+
+ nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, affmode);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFPY_YANG(no_link_params_affinity_mode, no_link_params_affinity_mode_cmd,
+ "no affinity-mode [<standard|extended|both>]",
+ NO_STR
+ "Interface affinity mode\n"
+ "Standard Admin-Group only RFC3630,5305,5329 (default)\n"
+ "Extended Admin-Group only RFC7308\n"
+ "Standard and extended Admin-Group format\n")
+{
+ const char *xpath = "./frr-zebra:zebra/link-params/affinity-mode";
+
+ nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, "standard");
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static int ag_iter_cb(const struct lyd_node *dnode, void *arg)
+{
+ struct vty *vty = (struct vty *)arg;
+
+ vty_out(vty, " %s", yang_dnode_get_string(dnode, "."));
+ return YANG_ITER_CONTINUE;
+}
+
+void cli_show_legacy_admin_group(struct vty *vty, const struct lyd_node *dnode,
+ bool show_defaults)
+{
+ if (!yang_dnode_exists(dnode, "./legacy-admin-group"))
+ return;
+
+ vty_out(vty, " admin-group 0x%x\n",
+ yang_dnode_get_uint32(dnode, "./legacy-admin-group"));
+}
+
+void cli_show_affinity_mode(struct vty *vty, const struct lyd_node *dnode,
+ bool show_defaults)
+{
+ enum affinity_mode affinity_mode = yang_dnode_get_enum(dnode, ".");
+
+ if (affinity_mode == AFFINITY_MODE_STANDARD)
+ vty_out(vty, " affinity-mode standard\n");
+ else if (affinity_mode == AFFINITY_MODE_BOTH)
+ vty_out(vty, " affinity-mode both\n");
+}
+
+void cli_show_affinity(struct vty *vty, const struct lyd_node *dnode,
+ bool show_defaults)
+{
+ if (!yang_dnode_exists(dnode, "./affinity"))
+ return;
+
+ vty_out(vty, " affinity");
+ yang_dnode_iterate(ag_iter_cb, vty, dnode, "./affinity");
+ vty_out(vty, "\n");
+}
+
int if_ip_address_install(struct interface *ifp, struct prefix *prefix,
const char *label, struct prefix *pp)
{
@@ -4523,6 +4710,8 @@ DEFUN (no_ipv6_address,
static int link_params_config_write(struct vty *vty, struct interface *ifp)
{
+ const struct lyd_node *dnode;
+ char xpath[XPATH_MAXLEN];
int i;
if ((ifp == NULL) || !HAS_LINK_PARAMS(ifp))
@@ -4545,8 +4734,15 @@ static int link_params_config_write(struct vty *vty, struct interface *ifp)
vty_out(vty, " unrsv-bw %d %g\n", i,
iflp->unrsv_bw[i]);
}
- if (IS_PARAM_SET(iflp, LP_ADM_GRP))
- vty_out(vty, " admin-grp 0x%x\n", iflp->admin_grp);
+
+ snprintf(
+ xpath, sizeof(xpath),
+ "/frr-interface:lib/interface[name='%s']/frr-zebra:zebra/link-params",
+ ifp->name);
+ dnode = yang_dnode_get(running_config->dnode, xpath);
+ if (dnode)
+ nb_cli_show_dnode_cmds(vty, dnode, false);
+
if (IS_PARAM_SET(iflp, LP_DELAY)) {
vty_out(vty, " delay %u", iflp->av_delay);
if (IS_PARAM_SET(iflp, LP_MM_DELAY)) {
@@ -4568,6 +4764,7 @@ static int link_params_config_write(struct vty *vty, struct interface *ifp)
if (IS_PARAM_SET(iflp, LP_RMT_AS))
vty_out(vty, " neighbor %pI4 as %u\n", &iflp->rmt_ip,
iflp->rmt_as);
+
vty_out(vty, " exit-link-params\n");
return 0;
}
@@ -4727,6 +4924,9 @@ void zebra_if_init(void)
install_element(LINK_PARAMS_NODE, &no_link_params_res_bw_cmd);
install_element(LINK_PARAMS_NODE, &link_params_use_bw_cmd);
install_element(LINK_PARAMS_NODE, &no_link_params_use_bw_cmd);
+ install_element(LINK_PARAMS_NODE, &link_params_affinity_cmd);
+ install_element(LINK_PARAMS_NODE, &link_params_affinity_mode_cmd);
+ install_element(LINK_PARAMS_NODE, &no_link_params_affinity_mode_cmd);
install_element(LINK_PARAMS_NODE, &exit_link_params_cmd);
/* setup EVPN MH elements */