#include "zebra/rt_netlink.h"
#include "zebra/interface.h"
#include "zebra/zebra_vxlan.h"
+#include "zebra/zebra_errors.h"
+
+DEFINE_MTYPE_STATIC(ZEBRA, ZINFO, "Zebra Interface Information")
#define ZEBRA_PTM_SUPPORT
struct route_node *node)
{
if (node->info)
- list_delete_and_null((struct list **)&node->info);
+ list_delete((struct list **)&node->info);
route_node_destroy(delegate, table, node);
}
{
struct zebra_if *zebra_if;
- zebra_if = XCALLOC(MTYPE_TMP, sizeof(struct zebra_if));
+ zebra_if = XCALLOC(MTYPE_ZINFO, sizeof(struct zebra_if));
zebra_if->multicast = IF_ZEBRA_MULTICAST_UNSPEC;
zebra_if->shutdown = IF_ZEBRA_SHUTDOWN_OFF;
}
#endif /* HAVE_RTADV */
+ memset(&zebra_if->neigh_mac[0], 0, 6);
+
/* Initialize installed address chains tree. */
zebra_if->ipv4_subnets =
route_table_init_with_delegate(&zebra_if_table_delegate);
struct rtadvconf *rtadv;
rtadv = &zebra_if->rtadv;
- list_delete_and_null(&rtadv->AdvPrefixList);
+ list_delete(&rtadv->AdvPrefixList);
#endif /* HAVE_RTADV */
THREAD_OFF(zebra_if->speed_update);
- XFREE(MTYPE_TMP, zebra_if);
+ XFREE(MTYPE_ZINFO, zebra_if);
}
return 0;
if (rn->info) {
ifp = (struct interface *)rn->info;
route_unlock_node(rn); /* get */
- ifp->node = rn;
return ifp;
}
return NULL;
}
-/* this function must be used only if the vrf backend
- * is a netns backend
- */
-struct interface *if_lookup_by_name_not_ns(ns_id_t ns_id,
- const char *ifname)
-{
- struct interface *ifp;
- struct ns *ns;
-
- RB_FOREACH (ns, ns_head, &ns_tree) {
- if (ns->ns_id == ns_id)
- continue;
- /* if_delete_update has removed interface
- * from zns->if_table
- * so to look for interface, use the vrf list
- */
- ifp = if_lookup_by_name(ifname, (vrf_id_t)ns->ns_id);
- if (!ifp)
- continue;
- return ifp;
- }
- return NULL;
-}
-
const char *ifindex2ifname_per_ns(struct zebra_ns *zns, unsigned int ifindex)
{
struct interface *ifp;
/* Get address derived subnet node. */
rn = route_node_lookup(zebra_if->ipv4_subnets, &cp);
if (!(rn && rn->info)) {
- zlog_warn(
- "Trying to remove an address from an unknown subnet."
- " (please report this bug)");
+ flog_warn(EC_ZEBRA_REMOVE_ADDR_UNKNOWN_SUBNET,
+ "Trying to remove an address from an unknown subnet."
+ " (please report this bug)");
return -1;
}
route_unlock_node(rn);
* In any case, we shouldn't decrement the lock counter if the address
* is unknown. */
if (!listnode_lookup(addr_list, ifc)) {
- zlog_warn(
+ flog_warn(
+ EC_ZEBRA_REMOVE_UNREGISTERED_ADDR,
"Trying to remove an address from a subnet where it is not"
" currently registered. (please report this bug)");
return -1;
}
/* Otherwise, free list and route node. */
- list_delete_and_null(&addr_list);
+ list_delete(&addr_list);
rn->info = NULL;
route_unlock_node(rn);
ret = if_set_prefix(ifp, ifc);
if (ret < 0) {
- zlog_warn(
+ flog_err_sys(
+ EC_ZEBRA_IFACE_ADDR_ADD_FAILED,
"Can't set interface's address: %s",
safe_strerror(errno));
continue;
ret = if_prefix_add_ipv6(ifp, ifc);
if (ret < 0) {
- zlog_warn(
+ flog_err_sys(
+ EC_ZEBRA_IFACE_ADDR_ADD_FAILED,
"Can't set interface's address: %s",
safe_strerror(errno));
continue;
}
/* Free chain list and respective route node. */
- list_delete_and_null(&addr_list);
+ list_delete(&addr_list);
rn->info = NULL;
route_unlock_node(rn);
} else if (cp.family == AF_INET6) {
if (if_is_up(ifp)) {
flog_err(
- LIB_ERR_INTERFACE,
+ EC_LIB_INTERFACE,
"interface %s vrf %u index %d is still up while being deleted.",
ifp->name, ifp->vrf_id, ifp->ifindex);
return;
ifp->node = NULL;
/* if the ifp is in a vrf, move it to default so vrf can be deleted if
- * desired */
- if (ifp->vrf_id)
+ * desired. This operation is not done for netns implementation to avoid
+ * collision with interface with the same name in the default vrf (can
+ * occur with this implementation whereas it is not possible with
+ * vrf-lite).
+ */
+ if (ifp->vrf_id && !vrf_is_backend_netns())
if_handle_vrf_change(ifp, VRF_DEFAULT);
/* Reset some zebra interface params to default values. */
mac[5] = address->s6_addr[15];
}
-void if_nbr_ipv6ll_to_ipv4ll_neigh_update(struct interface *ifp,
- struct in6_addr *address, int add)
+void if_nbr_mac_to_ipv4ll_neigh_update(struct interface *ifp,
+ char mac[6],
+ struct in6_addr *address,
+ int add)
{
struct zebra_vrf *zvrf = vrf_info_lookup(ifp->vrf_id);
struct zebra_if *zif = ifp->info;
char buf[16] = "169.254.0.1";
struct in_addr ipv4_ll;
- char mac[6];
ns_id_t ns_id;
inet_pton(AF_INET, buf, &ipv4_ll);
- ipv6_ll_address_to_mac(address, (uint8_t *)mac);
ns_id = zvrf->zns->ns_id;
/*
- * Remove existed arp record for the interface as netlink
- * protocol does not have update message types
- *
- * supported message types are RTM_NEWNEIGH and RTM_DELNEIGH
+ * Remove and re-add any existing neighbor entry for this address,
+ * since Netlink doesn't currently offer update message types.
*/
kernel_neigh_update(0, ifp->ifindex, ipv4_ll.s_addr, mac, 6, ns_id);
- /* Add arp record */
- kernel_neigh_update(add, ifp->ifindex, ipv4_ll.s_addr, mac, 6, ns_id);
+ /* Add new neighbor entry.
+ *
+ * We force installation even if current neighbor entry is the same.
+ * Since this function is used to refresh our MAC entries after an
+ * interface flap, if we don't force in our custom entries with their
+ * state set to PERMANENT or REACHABLE then the kernel will attempt to
+ * resolve our leftover entries, fail, mark them unreachable and then
+ * they'll be useless to us.
+ */
+ if (add)
+ kernel_neigh_update(add, ifp->ifindex, ipv4_ll.s_addr, mac, 6,
+ ns_id);
+
+ memcpy(&zif->neigh_mac[0], &mac[0], 6);
/*
* We need to note whether or not we originated a v6
zvrf->neigh_updates++;
}
+void if_nbr_ipv6ll_to_ipv4ll_neigh_update(struct interface *ifp,
+ struct in6_addr *address, int add)
+{
+
+ char mac[6];
+
+ ipv6_ll_address_to_mac(address, (uint8_t *)mac);
+ if_nbr_mac_to_ipv4ll_neigh_update(ifp, mac, address, add);
+}
+
static void if_nbr_ipv6ll_to_ipv4ll_neigh_add_all(struct interface *ifp)
{
if (listhead(ifp->nbr_connected)) {
/* Notify the protocol daemons. */
if (ifp->ptm_enable && (ifp->ptm_status == ZEBRA_PTM_STATUS_DOWN)) {
- zlog_warn("%s: interface %s hasn't passed ptm check\n",
+ flog_warn(EC_ZEBRA_PTM_NOT_READY,
+ "%s: interface %s hasn't passed ptm check\n",
__func__, ifp->name);
return;
}
if_get_flags(ifp);
}
-void zebra_if_update_link(struct interface *ifp, ifindex_t link_ifindex)
+void zebra_if_update_link(struct interface *ifp, ifindex_t link_ifindex,
+ ns_id_t ns_id)
{
struct zebra_if *zif;
+ if (IS_ZEBRA_IF_VETH(ifp))
+ return;
zif = (struct zebra_if *)ifp->info;
zif->link_ifindex = link_ifindex;
- zif->link = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
+ zif->link = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id),
link_ifindex);
}
+/*
+ * during initial link dump kernel does not order lower devices before
+ * upper devices so we need to fixup link dependencies at the end of dump
+ */
+void zebra_if_update_all_links(void)
+{
+ struct route_node *rn;
+ struct interface *ifp;
+ struct zebra_if *zif;
+ struct zebra_ns *ns;
+
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_info("fixup link dependencies");
+
+ ns = zebra_ns_lookup(NS_DEFAULT);
+ for (rn = route_top(ns->if_table); rn; rn = route_next(rn)) {
+ ifp = (struct interface *)rn->info;
+ if (!ifp)
+ continue;
+ zif = ifp->info;
+ if ((zif->link_ifindex != IFINDEX_INTERNAL) && !zif->link) {
+ zif->link = if_lookup_by_index_per_ns(ns,
+ zif->link_ifindex);
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug("interface %s/%d's lower fixup to %s/%d",
+ ifp->name, ifp->ifindex,
+ zif->link?zif->link->name:"unk",
+ zif->link_ifindex);
+ }
+ }
+}
+
+
/* Output prefix string to vty. */
static int prefix_vty_out(struct vty *vty, struct prefix *p)
return "VRF";
break;
+ case ZEBRA_IF_VETH:
+ return "VETH";
+ break;
+
+ case ZEBRA_IF_BOND:
+ return "bond";
+
+ case ZEBRA_IF_BOND_SLAVE:
+ return "bond_slave";
+
+ case ZEBRA_IF_MACVLAN:
+ return "macvlan";
+
default:
return "Unknown";
break;
br_slave->bridge_ifindex);
}
+ if (IS_ZEBRA_IF_BOND_SLAVE(ifp)) {
+ struct zebra_l2info_bondslave *bond_slave;
+
+ bond_slave = &zebra_if->bondslave_info;
+ if (bond_slave->bond_ifindex != IFINDEX_INTERNAL)
+ vty_out(vty, " Master (bond) ifindex %u\n",
+ bond_slave->bond_ifindex);
+ }
+
if (zebra_if->link_ifindex != IFINDEX_INTERNAL) {
vty_out(vty, " Link ifindex %u", zebra_if->link_ifindex);
if (zebra_if->link)
static int ipv6_address_install(struct vty *vty, struct interface *ifp,
const char *addr_str, const char *peer_str,
- const char *label, int secondary)
+ const char *label)
{
struct zebra_if *if_data;
struct prefix_ipv6 cp;
*p = cp;
ifc->address = (struct prefix *)p;
- /* Secondary. */
- if (secondary)
- SET_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY);
-
/* Label. */
if (label)
ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label);
static int ipv6_address_uninstall(struct vty *vty, struct interface *ifp,
const char *addr_str, const char *peer_str,
- const char *label, int secondry)
+ const char *label)
{
struct prefix_ipv6 cp;
struct connected *ifc;
int idx_ipv6_prefixlen = 2;
VTY_DECLVAR_CONTEXT(interface, ifp);
return ipv6_address_install(vty, ifp, argv[idx_ipv6_prefixlen]->arg,
- NULL, NULL, 0);
+ NULL, NULL);
}
DEFUN (no_ipv6_address,
int idx_ipv6_prefixlen = 3;
VTY_DECLVAR_CONTEXT(interface, ifp);
return ipv6_address_uninstall(vty, ifp, argv[idx_ipv6_prefixlen]->arg,
- NULL, NULL, 0);
+ NULL, NULL);
}
static int link_params_config_write(struct vty *vty, struct interface *ifp)
static int if_config_write(struct vty *vty)
{
- struct vrf *vrf;
+ struct vrf *vrf0;
struct interface *ifp;
zebra_ptm_write(vty);
- RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
- FOR_ALL_INTERFACES (vrf, ifp) {
+ RB_FOREACH (vrf0, vrf_name_head, &vrfs_by_name)
+ FOR_ALL_INTERFACES (vrf0, ifp) {
struct zebra_if *if_data;
struct listnode *addrnode;
struct connected *ifc;