summaryrefslogtreecommitdiffstats
path: root/zebra/zebra_l2.c
diff options
context:
space:
mode:
authorvivek <vivek@cumulusnetworks.com>2017-05-15 07:31:08 +0200
committerDonald Sharp <sharpd@cumulusnetworks.com>2017-07-12 18:22:19 +0200
commit6675513d00b8cb59942ecb05f990852d14ef3e41 (patch)
treee16818db2793aefeea3f7f7bcd2559e78f895e9f /zebra/zebra_l2.c
parentMerge pull request #791 from LabNConsulting/working/master/patch-set/style (diff)
downloadfrr-6675513d00b8cb59942ecb05f990852d14ef3e41.tar.xz
frr-6675513d00b8cb59942ecb05f990852d14ef3e41.zip
zebra: Layer-2 interface handling
Define interface types of interest and recognize the types. Store layer-2 information (VLAN Id, VNI etc.) for interfaces, process bridge interfaces and map bridge members to bridge. Display all the additional information to user (through "show interface"). Note: Only implemented for the netlink interface. Signed-off-by: Vivek Venkatraman <vivek@cumulusnetworks.com> Reviewed-by: Donald Sharp <sharpd@cumulusnetworks.com>
Diffstat (limited to 'zebra/zebra_l2.c')
-rw-r--r--zebra/zebra_l2.c238
1 files changed, 238 insertions, 0 deletions
diff --git a/zebra/zebra_l2.c b/zebra/zebra_l2.c
new file mode 100644
index 000000000..5dd83baed
--- /dev/null
+++ b/zebra/zebra_l2.c
@@ -0,0 +1,238 @@
+/*
+ * Zebra Layer-2 interface handling code
+ * Copyright (C) 2016, 2017 Cumulus Networks, Inc.
+ *
+ * This file is part of FRR.
+ *
+ * FRR 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.
+ *
+ * FRR 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 FRR; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <zebra.h>
+
+#include "if.h"
+#include "prefix.h"
+#include "table.h"
+#include "memory.h"
+#include "log.h"
+#include "linklist.h"
+#include "stream.h"
+#include "hash.h"
+#include "jhash.h"
+
+#include "zebra/rib.h"
+#include "zebra/rt.h"
+#include "zebra/zebra_ns.h"
+#include "zebra/zserv.h"
+#include "zebra/debug.h"
+#include "zebra/interface.h"
+#include "zebra/zebra_memory.h"
+#include "zebra/zebra_vrf.h"
+#include "zebra/rt_netlink.h"
+#include "zebra/zebra_l2.h"
+
+/* definitions */
+
+/* static function declarations */
+
+/* Private functions */
+static void
+map_slaves_to_bridge (struct interface *br_if, int link)
+{
+ struct vrf *vrf;
+ struct listnode *node;
+ struct interface *ifp;
+
+ RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
+ {
+ for (ALL_LIST_ELEMENTS_RO (vrf->iflist, node, ifp))
+ {
+ struct zebra_if *zif;
+ struct zebra_l2info_brslave *br_slave;
+
+ if (ifp->ifindex == IFINDEX_INTERNAL ||
+ !ifp->info)
+ continue;
+ if (!IS_ZEBRA_IF_BRIDGE_SLAVE (ifp))
+ continue;
+
+ /* NOTE: This assumes 'zebra_l2info_brslave' is the first field
+ * for any L2 interface.
+ */
+ zif = (struct zebra_if *) ifp->info;
+ br_slave = &zif->brslave_info;
+
+ if (link)
+ {
+ if (br_slave->bridge_ifindex == br_if->ifindex)
+ br_slave->br_if = br_if;
+ }
+ else
+ {
+ if (br_slave->br_if == br_if)
+ br_slave->br_if = NULL;
+ }
+ }
+ }
+}
+
+/* Public functions */
+void
+zebra_l2_map_slave_to_bridge (struct zebra_l2info_brslave *br_slave)
+{
+ struct interface *br_if;
+
+ /* TODO: Handle change of master */
+ br_if = if_lookup_by_index_per_ns (zebra_ns_lookup (NS_DEFAULT),
+ br_slave->bridge_ifindex);
+ if (br_if)
+ br_slave->br_if = br_if;
+}
+
+void
+zebra_l2_unmap_slave_from_bridge (struct zebra_l2info_brslave *br_slave)
+{
+ br_slave->br_if = NULL;
+}
+
+/*
+ * Handle Bridge interface add or update. Update relevant info,
+ * map slaves (if any) to the bridge.
+ */
+void
+zebra_l2_bridge_add_update (struct interface *ifp,
+ struct zebra_l2info_bridge *bridge_info,
+ int add)
+{
+ struct zebra_if *zif;
+
+ zif = ifp->info;
+ assert(zif);
+
+ /* Copy over the L2 information. */
+ memcpy (&zif->l2info.br, bridge_info, sizeof (*bridge_info));
+
+ /* Link all slaves to this bridge */
+ map_slaves_to_bridge (ifp, 1);
+}
+
+/*
+ * Handle Bridge interface delete.
+ */
+void
+zebra_l2_bridge_del (struct interface *ifp)
+{
+ /* Unlink all slaves to this bridge */
+ map_slaves_to_bridge (ifp, 0);
+}
+
+/*
+ * Update L2 info for a VLAN interface. Only relevant parameter is the
+ * VLAN Id and this cannot change.
+ */
+void
+zebra_l2_vlanif_update (struct interface *ifp,
+ struct zebra_l2info_vlan *vlan_info)
+{
+ struct zebra_if *zif;
+
+ zif = ifp->info;
+ assert(zif);
+
+ /* Copy over the L2 information. */
+ memcpy (&zif->l2info.vl, vlan_info, sizeof (*vlan_info));
+}
+
+/*
+ * Update L2 info for a VxLAN interface. This is called upon interface
+ * addition as well as update. Upon add, need to invoke the VNI create
+ * function. Upon update, the params of interest are the local tunnel
+ * IP and VLAN mapping, but the latter is handled separately.
+ */
+void
+zebra_l2_vxlanif_add_update (struct interface *ifp,
+ struct zebra_l2info_vxlan *vxlan_info,
+ int add)
+{
+ struct zebra_if *zif;
+ struct in_addr old_vtep_ip;
+
+ zif = ifp->info;
+ assert(zif);
+
+ if (add)
+ {
+ memcpy (&zif->l2info.vxl, vxlan_info, sizeof (*vxlan_info));
+ return;
+ }
+
+ old_vtep_ip = zif->l2info.vxl.vtep_ip;
+ if (IPV4_ADDR_SAME(&old_vtep_ip, &vxlan_info->vtep_ip))
+ return;
+
+ zif->l2info.vxl.vtep_ip = vxlan_info->vtep_ip;
+}
+
+/*
+ * Handle change to VLAN to VNI mapping.
+ */
+void
+zebra_l2_vxlanif_update_access_vlan (struct interface *ifp,
+ vlanid_t access_vlan)
+{
+ struct zebra_if *zif;
+
+ zif = ifp->info;
+ assert(zif);
+
+ zif->l2info.vxl.access_vlan = access_vlan;
+}
+
+/*
+ * Handle VxLAN interface delete.
+ */
+void
+zebra_l2_vxlanif_del (struct interface *ifp)
+{
+ /* No action currently. */
+}
+
+/*
+ * Map or unmap interface from bridge.
+ * NOTE: It is currently assumped that an interface has to be unmapped
+ * from a bridge before it can be mapped to another bridge.
+ */
+void
+zebra_l2if_update_bridge_slave (struct interface *ifp,
+ ifindex_t bridge_ifindex)
+{
+ struct zebra_if *zif;
+ ifindex_t old_bridge_ifindex;
+
+ zif = ifp->info;
+ assert(zif);
+
+ old_bridge_ifindex = zif->brslave_info.bridge_ifindex;
+ if (old_bridge_ifindex == bridge_ifindex)
+ return;
+
+ zif->brslave_info.bridge_ifindex = bridge_ifindex;
+
+ /* Set up or remove link with master */
+ if (bridge_ifindex != IFINDEX_INTERNAL)
+ zebra_l2_map_slave_to_bridge (&zif->brslave_info);
+ else if (old_bridge_ifindex != IFINDEX_INTERNAL)
+ zebra_l2_unmap_slave_from_bridge (&zif->brslave_info);
+}