summaryrefslogtreecommitdiff
path: root/zebra/interface.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/interface.c')
-rw-r--r--zebra/interface.c271
1 files changed, 180 insertions, 91 deletions
diff --git a/zebra/interface.c b/zebra/interface.c
index 21eeb20543..8b5dbabb92 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -584,7 +584,7 @@ void if_add_update(struct interface *ifp)
{
struct zebra_if *if_data;
struct zebra_ns *zns;
- struct zebra_vrf *zvrf = vrf_info_lookup(ifp->vrf_id);
+ struct zebra_vrf *zvrf = ifp->vrf->info;
/* case interface populate before vrf enabled */
if (zvrf->zns)
@@ -611,8 +611,8 @@ void if_add_update(struct interface *ifp)
if (IS_ZEBRA_DEBUG_KERNEL) {
zlog_debug(
"interface %s vrf %s(%u) index %d is shutdown. Won't wake it up.",
- ifp->name, VRF_LOGNAME(zvrf->vrf),
- ifp->vrf_id, ifp->ifindex);
+ ifp->name, ifp->vrf->name,
+ ifp->vrf->vrf_id, ifp->ifindex);
}
return;
@@ -623,14 +623,14 @@ void if_add_update(struct interface *ifp)
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
"interface %s vrf %s(%u) index %d becomes active.",
- ifp->name, VRF_LOGNAME(zvrf->vrf), ifp->vrf_id,
+ ifp->name, ifp->vrf->name, ifp->vrf->vrf_id,
ifp->ifindex);
} else {
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug("interface %s vrf %s(%u) index %d is added.",
- ifp->name, VRF_LOGNAME(zvrf->vrf),
- ifp->vrf_id, ifp->ifindex);
+ ifp->name, ifp->vrf->name, ifp->vrf->vrf_id,
+ ifp->ifindex);
}
}
@@ -769,12 +769,11 @@ void if_delete_update(struct interface *ifp)
struct zebra_if *zif;
if (if_is_up(ifp)) {
- struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
-
flog_err(
EC_LIB_INTERFACE,
"interface %s vrf %s(%u) index %d is still up while being deleted.",
- ifp->name, VRF_LOGNAME(vrf), ifp->vrf_id, ifp->ifindex);
+ ifp->name, ifp->vrf->name, ifp->vrf->vrf_id,
+ ifp->ifindex);
return;
}
@@ -784,13 +783,10 @@ void if_delete_update(struct interface *ifp)
/* Mark interface as inactive */
UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE);
- if (IS_ZEBRA_DEBUG_KERNEL) {
- struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
-
+ if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug("interface %s vrf %s(%u) index %d is now inactive.",
- ifp->name, VRF_LOGNAME(vrf), ifp->vrf_id,
+ ifp->name, ifp->vrf->name, ifp->vrf->vrf_id,
ifp->ifindex);
- }
/* Delete connected routes from the kernel. */
if_delete_connected(ifp);
@@ -814,7 +810,7 @@ void if_delete_update(struct interface *ifp)
* occur with this implementation whereas it is not possible with
* vrf-lite).
*/
- if (ifp->vrf_id && !vrf_is_backend_netns())
+ if (ifp->vrf->vrf_id && !vrf_is_backend_netns())
if_handle_vrf_change(ifp, VRF_DEFAULT);
/* Reset some zebra interface params to default values. */
@@ -842,7 +838,7 @@ void if_handle_vrf_change(struct interface *ifp, vrf_id_t vrf_id)
{
vrf_id_t old_vrf_id;
- old_vrf_id = ifp->vrf_id;
+ old_vrf_id = ifp->vrf->vrf_id;
/* Uninstall connected routes. */
if_uninstall_connected(ifp);
@@ -884,7 +880,7 @@ void if_nbr_mac_to_ipv4ll_neigh_update(struct interface *ifp,
struct in6_addr *address,
int add)
{
- struct zebra_vrf *zvrf = vrf_info_lookup(ifp->vrf_id);
+ struct zebra_vrf *zvrf = ifp->vrf->info;
struct zebra_if *zif = ifp->info;
char buf[16] = "169.254.0.1";
struct in_addr ipv4_ll;
@@ -1022,11 +1018,11 @@ void if_up(struct interface *ifp)
{
struct zebra_if *zif;
struct interface *link_if;
- struct zebra_vrf *zvrf = vrf_info_lookup(ifp->vrf_id);
+ struct zebra_vrf *zvrf = ifp->vrf->info;
zif = ifp->info;
zif->up_count++;
- quagga_timestamp(2, zif->up_last, sizeof(zif->up_last));
+ frr_timestamp(2, zif->up_last, sizeof(zif->up_last));
/* Notify the protocol daemons. */
if (ifp->ptm_enable && (ifp->ptm_status == ZEBRA_PTM_STATUS_DOWN)) {
@@ -1086,11 +1082,11 @@ void if_down(struct interface *ifp)
{
struct zebra_if *zif;
struct interface *link_if;
- struct zebra_vrf *zvrf = vrf_info_lookup(ifp->vrf_id);
+ struct zebra_vrf *zvrf = ifp->vrf->info;
zif = ifp->info;
zif->down_count++;
- quagga_timestamp(2, zif->down_last, sizeof(zif->down_last));
+ frr_timestamp(2, zif->down_last, sizeof(zif->down_last));
if_down_nhg_dependents(ifp);
@@ -1175,7 +1171,7 @@ void zebra_if_update_all_links(struct zebra_ns *zns)
zlog_debug("bond mbr %s map to bond %d",
zif->ifp->name,
zif->bondslave_info.bond_ifindex);
- zebra_l2_map_slave_to_bond(zif, ifp->vrf_id);
+ zebra_l2_map_slave_to_bond(zif, ifp->vrf->vrf_id);
}
/* update SVI linkages */
@@ -1205,13 +1201,115 @@ void zebra_if_set_protodown(struct interface *ifp, bool down)
#endif
}
+/*
+ * Handle an interface addr event based on info in a dplane context object.
+ * This runs in the main pthread, using the info in the context object to
+ * modify an interface.
+ */
+void zebra_if_addr_update_ctx(struct zebra_dplane_ctx *ctx)
+{
+ struct interface *ifp;
+ uint8_t flags = 0;
+ const char *label = NULL;
+ ns_id_t ns_id;
+ struct zebra_ns *zns;
+ uint32_t metric = METRIC_MAX;
+ ifindex_t ifindex;
+ const struct prefix *addr, *dest = NULL;
+ enum dplane_op_e op;
+
+ op = dplane_ctx_get_op(ctx);
+ ns_id = dplane_ctx_get_ns_id(ctx);
+
+ zns = zebra_ns_lookup(ns_id);
+ if (zns == NULL) {
+ /* No ns - deleted maybe? */
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug("%s: can't find zns id %u", __func__, ns_id);
+ goto done;
+ }
+
+ ifindex = dplane_ctx_get_ifindex(ctx);
+
+ ifp = if_lookup_by_index_per_ns(zns, ifindex);
+ if (ifp == NULL) {
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug("%s: can't find ifp at nsid %u index %d",
+ __func__, ns_id, ifindex);
+ goto done;
+ }
+
+ addr = dplane_ctx_get_intf_addr(ctx);
+
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug("%s: %s: ifindex %u, addr %pFX", __func__,
+ dplane_op2str(op), ifindex, addr);
+
+ /* Is there a peer or broadcast address? */
+ dest = dplane_ctx_get_intf_dest(ctx);
+ if (dest->prefixlen == 0)
+ dest = NULL;
+
+ if (dplane_ctx_intf_is_connected(ctx))
+ SET_FLAG(flags, ZEBRA_IFA_PEER);
+
+ /* Flags. */
+ if (dplane_ctx_intf_is_secondary(ctx))
+ SET_FLAG(flags, ZEBRA_IFA_SECONDARY);
+
+ /* Label? */
+ if (dplane_ctx_intf_has_label(ctx))
+ label = dplane_ctx_get_intf_label(ctx);
+
+ if (label && strcmp(ifp->name, label) == 0)
+ label = NULL;
+
+ metric = dplane_ctx_get_intf_metric(ctx);
+
+ /* Register interface address to the interface. */
+ if (addr->family == AF_INET) {
+ if (op == DPLANE_OP_INTF_ADDR_ADD)
+ connected_add_ipv4(
+ ifp, flags, &addr->u.prefix4, addr->prefixlen,
+ dest ? &dest->u.prefix4 : NULL, label, metric);
+ else if (CHECK_FLAG(flags, ZEBRA_IFA_PEER)) {
+ /* Delete with a peer address */
+ connected_delete_ipv4(ifp, flags, &addr->u.prefix4,
+ addr->prefixlen,
+ &dest->u.prefix4);
+ } else
+ connected_delete_ipv4(ifp, flags, &addr->u.prefix4,
+ addr->prefixlen, NULL);
+ }
+
+ if (addr->family == AF_INET6) {
+ if (op == DPLANE_OP_INTF_ADDR_ADD) {
+ connected_add_ipv6(ifp, flags, &addr->u.prefix6,
+ dest ? &dest->u.prefix6 : NULL,
+ addr->prefixlen, label, metric);
+ } else
+ connected_delete_ipv6(ifp, &addr->u.prefix6, NULL,
+ addr->prefixlen);
+ }
+
+ /*
+ * Linux kernel does not send route delete on interface down/addr del
+ * so we have to re-process routes it owns (i.e. kernel routes)
+ */
+ if (op != DPLANE_OP_INTF_ADDR_ADD)
+ rib_update(RIB_UPDATE_KERNEL);
+
+done:
+ /* We're responsible for the ctx object */
+ dplane_ctx_fini(&ctx);
+}
+
/* Dump if address information to vty. */
static void connected_dump_vty(struct vty *vty, json_object *json,
struct connected *connected)
{
struct prefix *p;
json_object *json_addr = NULL;
- char buf[PREFIX2STR_BUFFER];
/* Print interface address. */
p = connected->address;
@@ -1219,8 +1317,7 @@ static void connected_dump_vty(struct vty *vty, json_object *json,
if (json) {
json_addr = json_object_new_object();
json_object_array_add(json, json_addr);
- json_object_string_add(json_addr, "address",
- prefix2str(p, buf, sizeof(buf)));
+ json_object_string_addf(json_addr, "address", "%pFX", p);
} else {
vty_out(vty, " %s %pFX", prefix_family_str(p), p);
}
@@ -1228,10 +1325,8 @@ static void connected_dump_vty(struct vty *vty, json_object *json,
/* If there is destination address, print it. */
if (CONNECTED_PEER(connected) && connected->destination) {
if (json) {
- json_object_string_add(
- json_addr, "peer",
- prefix2str(connected->destination, buf,
- sizeof(buf)));
+ json_object_string_addf(json_addr, "peer", "%pFX",
+ connected->destination);
} else {
vty_out(vty, " peer %pFX", connected->destination);
}
@@ -1278,7 +1373,8 @@ static void nbr_connected_dump_vty(struct vty *vty, json_object *json,
vty_out(vty, " %s %pFX\n", prefix_family_str(p), p);
}
-static const char *zebra_zifslavetype_2str(zebra_slave_iftype_t zif_slave_type)
+static const char *
+zebra_zifslavetype_2str(enum zebra_slave_iftype zif_slave_type)
{
switch (zif_slave_type) {
case ZEBRA_IF_SLAVE_BRIDGE:
@@ -1295,7 +1391,7 @@ static const char *zebra_zifslavetype_2str(zebra_slave_iftype_t zif_slave_type)
return "None";
}
-static const char *zebra_ziftype_2str(zebra_iftype_t zif_type)
+static const char *zebra_ziftype_2str(enum zebra_iftype zif_type)
{
switch (zif_type) {
case ZEBRA_IF_OTHER:
@@ -1512,7 +1608,6 @@ static void if_dump_vty(struct vty *vty, struct interface *ifp)
struct listnode *node;
struct route_node *rn;
struct zebra_if *zebra_if;
- struct vrf *vrf;
char pd_buf[ZEBRA_PROTODOWN_RC_STR_LEN];
zebra_if = ifp->info;
@@ -1540,8 +1635,7 @@ static void if_dump_vty(struct vty *vty, struct interface *ifp)
zebra_ptm_show_status(vty, NULL, ifp);
- vrf = vrf_lookup_by_id(ifp->vrf_id);
- vty_out(vty, " vrf: %s\n", vrf->name);
+ vty_out(vty, " vrf: %s\n", ifp->vrf->name);
if (ifp->desc)
vty_out(vty, " Description: %s\n", ifp->desc);
@@ -1837,7 +1931,6 @@ static void if_dump_vty_json(struct vty *vty, struct interface *ifp,
struct listnode *node;
struct route_node *rn;
struct zebra_if *zebra_if;
- struct vrf *vrf;
char pd_buf[ZEBRA_PROTODOWN_RC_STR_LEN];
char buf[BUFSIZ];
json_object *json_if;
@@ -1875,8 +1968,7 @@ static void if_dump_vty_json(struct vty *vty, struct interface *ifp,
zebra_ptm_show_status(vty, json, ifp);
- vrf = vrf_lookup_by_id(ifp->vrf_id);
- json_object_string_add(json_if, "vrfName", vrf->name);
+ json_object_string_add(json_if, "vrfName", ifp->vrf->name);
if (ifp->desc)
json_object_string_add(json_if, "description", ifp->desc);
@@ -1962,18 +2054,14 @@ static void if_dump_vty_json(struct vty *vty, struct interface *ifp,
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_add(json_if, "vtepIp",
- inet_ntop(AF_INET,
- &vxlan_info->vtep_ip,
- buf, sizeof(buf)));
+ 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_add(json_if, "mcastGroup",
- inet_ntop(AF_INET,
- &vxlan_info->mcast_grp,
- buf, sizeof(buf)));
+ 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;
@@ -1990,16 +2078,12 @@ static void if_dump_vty_json(struct vty *vty, struct interface *ifp,
gre_info = &zebra_if->l2info.gre;
if (gre_info->vtep_ip.s_addr != INADDR_ANY) {
- json_object_string_add(json_if, "vtepIp",
- inet_ntop(AF_INET,
- &gre_info->vtep_ip,
- buf, sizeof(buf)));
+ json_object_string_addf(json_if, "vtepIp", "%pI4",
+ &gre_info->vtep_ip);
if (gre_info->vtep_ip_remote.s_addr != INADDR_ANY)
- json_object_string_add(
- json_if, "vtepRemoteIp",
- inet_ntop(AF_INET,
- &gre_info->vtep_ip_remote,
- buf, sizeof(buf)));
+ json_object_string_addf(
+ json_if, "vtepRemoteIp", "%pI4",
+ &gre_info->vtep_ip_remote);
}
if (gre_info->ifindex_link
&& (gre_info->link_nsid != NS_UNKNOWN)) {
@@ -2133,9 +2217,8 @@ static void if_dump_vty_json(struct vty *vty, struct interface *ifp,
json_object_double_add(json_te, "utilizedBandwidth",
iflp->use_bw);
if (IS_PARAM_SET(iflp, LP_RMT_AS))
- json_object_string_add(json_te, "neighborAsbrIp",
- inet_ntop(AF_INET, &iflp->rmt_ip,
- buf, sizeof(buf)));
+ json_object_string_addf(json_te, "neighborAsbrIp",
+ "%pI4", &iflp->rmt_ip);
json_object_int_add(json_te, "neighborAsbrAs", iflp->rmt_as);
}
@@ -2261,12 +2344,8 @@ DEFPY(show_interface, show_interface_cmd,
}
}
- if (json) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (json)
+ vty_json(vty, json);
return CMD_SUCCESS;
}
@@ -2308,12 +2387,8 @@ DEFPY (show_interface_vrf_all,
}
}
- if (json) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (json)
+ vty_json(vty, json);
return CMD_SUCCESS;
}
@@ -2361,12 +2436,8 @@ DEFPY (show_interface_name_vrf,
else
if_dump_vty(vty, ifp);
- if (json) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (json)
+ vty_json(vty, json);
return CMD_SUCCESS;
}
@@ -2381,12 +2452,24 @@ DEFPY (show_interface_name_vrf_all,
VRF_ALL_CMD_HELP_STR
JSON_STR)
{
- struct interface *ifp;
+ struct interface *ifp = NULL;
+ struct interface *ifptmp;
+ struct vrf *vrf;
json_object *json = NULL;
+ int count = 0;
interface_update_stats();
- ifp = if_lookup_by_name_all_vrf(ifname);
+ RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
+ ifptmp = if_lookup_by_name_vrf(ifname, vrf);
+ if (ifptmp) {
+ ifp = ifptmp;
+ count++;
+ if (!vrf_is_backend_netns())
+ break;
+ }
+ }
+
if (ifp == NULL) {
if (uj)
vty_out(vty, "{}\n");
@@ -2394,6 +2477,17 @@ DEFPY (show_interface_name_vrf_all,
vty_out(vty, "%% Can't find interface %s\n", ifname);
return CMD_WARNING;
}
+ if (count > 1) {
+ if (uj) {
+ vty_out(vty, "{}\n");
+ } else {
+ vty_out(vty,
+ "%% There are multiple interfaces with name %s\n",
+ ifname);
+ vty_out(vty, "%% You must specify the VRF name\n");
+ }
+ return CMD_WARNING;
+ }
if (uj)
json = json_object_new_object();
@@ -2403,12 +2497,8 @@ DEFPY (show_interface_name_vrf_all,
else
if_dump_vty(vty, ifp);
- if (json) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (json)
+ vty_json(vty, json);
return CMD_SUCCESS;
}
@@ -2782,6 +2872,7 @@ struct cmd_node link_params_node = {
.node = LINK_PARAMS_NODE,
.parent_node = INTERFACE_NODE,
.prompt = "%s(config-link-params)# ",
+ .no_xpath = true,
};
static void link_param_cmd_set_uint32(struct interface *ifp, uint32_t *field,
@@ -4096,29 +4187,27 @@ 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");
+ vty_out(vty, " exit-link-params\n");
return 0;
}
static int if_config_write(struct vty *vty)
{
- struct vrf *vrf0;
+ struct vrf *vrf;
struct interface *ifp;
zebra_ptm_write(vty);
- RB_FOREACH (vrf0, vrf_name_head, &vrfs_by_name)
- FOR_ALL_INTERFACES (vrf0, ifp) {
+ RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
+ FOR_ALL_INTERFACES (vrf, ifp) {
struct zebra_if *if_data;
struct listnode *addrnode;
struct connected *ifc;
struct prefix *p;
- struct vrf *vrf;
if_data = ifp->info;
- vrf = vrf_lookup_by_id(ifp->vrf_id);
- if (ifp->vrf_id == VRF_DEFAULT)
+ if (ifp->vrf->vrf_id == VRF_DEFAULT)
vty_frame(vty, "interface %s\n", ifp->name);
else
vty_frame(vty, "interface %s vrf %s\n",
@@ -4188,7 +4277,7 @@ static int if_config_write(struct vty *vty)
zebra_evpn_mh_if_write(vty, ifp);
link_params_config_write(vty, ifp);
- vty_endframe(vty, "!\n");
+ vty_endframe(vty, "exit\n!\n");
}
return 0;
}