mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-04-30 06:42:17 +00:00
zebra: MAC and Neighbor (ARP/ND) handling
Implement handling of MACs and Neighbors (ARP/ND entries) in zebra: - MAC and Neighbor database handlers - Read MACs and Neighbors from the kernel, when needed and create entries in zebra's MAC and Neighbor databases. - Handle add/update/delete notifications from the kernel for MACs and Neighbors and update zebra's database appropriately - Inform locally learnt MACs and Neighbors to client - Handle MACIP add/delete from client and install appriporiate entries into the kernel - Since Neighbor entries will be installed on an SVI, implement the needed mappings NOTE: kernel interface is only implemented for Linux/netlink Signed-off-by: Vivek Venkatraman <vivek@cumulusnetworks.com> Reviewed-by: Donald Sharp <sharpd@cumulusnetworks.com>
This commit is contained in:
parent
4122e25286
commit
2232a77c2b
@ -951,6 +951,10 @@ static const struct zebra_desc_table command_types[] = {
|
||||
DESC_ENTRY (ZEBRA_VNI_DEL),
|
||||
DESC_ENTRY (ZEBRA_REMOTE_VTEP_ADD),
|
||||
DESC_ENTRY (ZEBRA_REMOTE_VTEP_DEL),
|
||||
DESC_ENTRY (ZEBRA_MACIP_ADD),
|
||||
DESC_ENTRY (ZEBRA_MACIP_DEL),
|
||||
DESC_ENTRY (ZEBRA_REMOTE_MACIP_ADD),
|
||||
DESC_ENTRY (ZEBRA_REMOTE_MACIP_DEL),
|
||||
};
|
||||
#undef DESC_ENTRY
|
||||
|
||||
|
@ -101,6 +101,10 @@ typedef enum {
|
||||
ZEBRA_VNI_DEL,
|
||||
ZEBRA_REMOTE_VTEP_ADD,
|
||||
ZEBRA_REMOTE_VTEP_DEL,
|
||||
ZEBRA_MACIP_ADD,
|
||||
ZEBRA_MACIP_DEL,
|
||||
ZEBRA_REMOTE_MACIP_ADD,
|
||||
ZEBRA_REMOTE_MACIP_DEL,
|
||||
} zebra_message_types_t;
|
||||
|
||||
struct redist_proto
|
||||
|
@ -847,6 +847,7 @@ void
|
||||
if_up (struct interface *ifp)
|
||||
{
|
||||
struct zebra_if *zif;
|
||||
struct interface *link_if;
|
||||
|
||||
zif = ifp->info;
|
||||
zif->up_count++;
|
||||
@ -882,8 +883,23 @@ if_up (struct interface *ifp)
|
||||
|
||||
zebra_vrf_static_route_interface_fixup (ifp);
|
||||
|
||||
/* Handle interface up for specific types for EVPN. Non-VxLAN interfaces
|
||||
* are checked to see if (remote) neighbor entries need to be installed
|
||||
* on them for ARP suppression.
|
||||
*/
|
||||
if (IS_ZEBRA_IF_VXLAN (ifp))
|
||||
zebra_vxlan_if_up (ifp);
|
||||
else if (IS_ZEBRA_IF_BRIDGE (ifp))
|
||||
{
|
||||
link_if = ifp;
|
||||
zebra_vxlan_svi_up (ifp, link_if);
|
||||
}
|
||||
else if (IS_ZEBRA_IF_VLAN (ifp))
|
||||
{
|
||||
link_if = zif->link;
|
||||
if (link_if)
|
||||
zebra_vxlan_svi_up (ifp, link_if);
|
||||
}
|
||||
}
|
||||
|
||||
/* Interface goes down. We have to manage different behavior of based
|
||||
@ -892,13 +908,30 @@ void
|
||||
if_down (struct interface *ifp)
|
||||
{
|
||||
struct zebra_if *zif;
|
||||
struct interface *link_if;
|
||||
|
||||
zif = ifp->info;
|
||||
zif->down_count++;
|
||||
quagga_timestamp (2, zif->down_last, sizeof (zif->down_last));
|
||||
|
||||
/* Handle interface down for specific types for EVPN. Non-VxLAN interfaces
|
||||
* are checked to see if (remote) neighbor entries need to be purged
|
||||
* for ARP suppression.
|
||||
*/
|
||||
if (IS_ZEBRA_IF_VXLAN (ifp))
|
||||
zebra_vxlan_if_down (ifp);
|
||||
else if (IS_ZEBRA_IF_BRIDGE (ifp))
|
||||
{
|
||||
link_if = ifp;
|
||||
zebra_vxlan_svi_down (ifp, link_if);
|
||||
}
|
||||
else if (IS_ZEBRA_IF_VLAN (ifp))
|
||||
{
|
||||
link_if = zif->link;
|
||||
if (link_if)
|
||||
zebra_vxlan_svi_down (ifp, link_if);
|
||||
}
|
||||
|
||||
|
||||
/* Notify to the protocol daemons. */
|
||||
zebra_interface_down_update (ifp);
|
||||
|
@ -269,6 +269,12 @@ netlink_information_fetch (struct sockaddr_nl *snl, struct nlmsghdr *h,
|
||||
case RTM_DELADDR:
|
||||
return netlink_interface_addr (snl, h, ns_id, startup);
|
||||
break;
|
||||
case RTM_NEWNEIGH:
|
||||
return netlink_neigh_change (snl, h, ns_id);
|
||||
break;
|
||||
case RTM_DELNEIGH:
|
||||
return netlink_neigh_change (snl, h, ns_id);
|
||||
break;
|
||||
default:
|
||||
zlog_warn ("Unknown netlink nlmsg_type %d vrf %u\n", h->nlmsg_type,
|
||||
ns_id);
|
||||
@ -297,17 +303,21 @@ static void netlink_install_filter (int sock, __u32 pid)
|
||||
struct sock_filter filter[] = {
|
||||
/* 0: ldh [4] */
|
||||
BPF_STMT(BPF_LD|BPF_ABS|BPF_H, offsetof(struct nlmsghdr, nlmsg_type)),
|
||||
/* 1: jeq 0x18 jt 3 jf 6 */
|
||||
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_NEWROUTE), 1, 0),
|
||||
/* 2: jeq 0x19 jt 3 jf 6 */
|
||||
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_DELROUTE), 0, 3),
|
||||
/* 3: ldw [12] */
|
||||
/* 1: jeq 0x18 jt 5 jf next */
|
||||
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_NEWROUTE), 3, 0),
|
||||
/* 2: jeq 0x19 jt 5 jf next */
|
||||
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_DELROUTE), 2, 0),
|
||||
/* 3: jeq 0x19 jt 5 jf next */
|
||||
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_NEWNEIGH), 1, 0),
|
||||
/* 4: jeq 0x19 jt 5 jf 8 */
|
||||
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_DELNEIGH), 0, 3),
|
||||
/* 5: ldw [12] */
|
||||
BPF_STMT(BPF_LD|BPF_ABS|BPF_W, offsetof(struct nlmsghdr, nlmsg_pid)),
|
||||
/* 4: jeq XX jt 5 jf 6 */
|
||||
/* 6: jeq XX jt 7 jf 8 */
|
||||
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htonl(pid), 0, 1),
|
||||
/* 5: ret 0 (skip) */
|
||||
/* 7: ret 0 (skip) */
|
||||
BPF_STMT(BPF_RET|BPF_K, 0),
|
||||
/* 6: ret 0xffff (keep) */
|
||||
/* 8: ret 0xffff (keep) */
|
||||
BPF_STMT(BPF_RET|BPF_K, 0xffff),
|
||||
};
|
||||
|
||||
@ -786,7 +796,7 @@ kernel_init (struct zebra_ns *zns)
|
||||
/* Initialize netlink sockets */
|
||||
groups = RTMGRP_LINK | RTMGRP_IPV4_ROUTE | RTMGRP_IPV4_IFADDR |
|
||||
RTMGRP_IPV6_ROUTE | RTMGRP_IPV6_IFADDR |
|
||||
RTMGRP_IPV4_MROUTE;
|
||||
RTMGRP_IPV4_MROUTE | RTMGRP_NEIGH;
|
||||
|
||||
snprintf (zns->netlink.name, sizeof (zns->netlink.name),
|
||||
"netlink-listen (NS %u)", zns->ns_id);
|
||||
|
10
zebra/rt.h
10
zebra/rt.h
@ -24,6 +24,7 @@
|
||||
|
||||
#include "prefix.h"
|
||||
#include "if.h"
|
||||
#include "vlan.h"
|
||||
#include "vxlan.h"
|
||||
#include "zebra/rib.h"
|
||||
#include "zebra/zebra_ns.h"
|
||||
@ -46,4 +47,13 @@ extern int kernel_add_vtep (vni_t vni, struct interface *ifp,
|
||||
struct in_addr *vtep_ip);
|
||||
extern int kernel_del_vtep (vni_t vni, struct interface *ifp,
|
||||
struct in_addr *vtep_ip);
|
||||
extern int kernel_add_mac (struct interface *ifp, vlanid_t vid,
|
||||
struct ethaddr *mac, struct in_addr vtep_ip);
|
||||
extern int kernel_del_mac (struct interface *ifp, vlanid_t vid,
|
||||
struct ethaddr *mac, struct in_addr vtep_ip, int local);
|
||||
|
||||
extern int kernel_add_neigh (struct interface *ifp, struct ipaddr *ip,
|
||||
struct ethaddr *mac);
|
||||
extern int kernel_del_neigh (struct interface *ifp, struct ipaddr *ip);
|
||||
|
||||
#endif /* _ZEBRA_RT_H */
|
||||
|
@ -56,6 +56,7 @@
|
||||
#include "zebra/kernel_netlink.h"
|
||||
#include "zebra/rt_netlink.h"
|
||||
#include "zebra/zebra_mroute.h"
|
||||
#include "zebra/zebra_vxlan.h"
|
||||
|
||||
|
||||
/* TODO - Temporary definitions, need to refine. */
|
||||
@ -94,8 +95,22 @@
|
||||
#ifndef NDA_MASTER
|
||||
#define NDA_MASTER 9
|
||||
#endif
|
||||
|
||||
#ifndef NTF_SELF
|
||||
#define NTF_SELF 0x02
|
||||
#endif
|
||||
|
||||
#ifndef NTF_EXT_LEARNED
|
||||
#define NTF_EXT_LEARNED 0x10
|
||||
#endif
|
||||
|
||||
#ifndef NDA_VLAN
|
||||
#define NDA_VLAN 5
|
||||
#endif
|
||||
/* End of temporary definitions */
|
||||
|
||||
static vlanid_t filter_vlan = 0;
|
||||
|
||||
struct gw_family_t
|
||||
{
|
||||
u_int16_t filler;
|
||||
@ -1622,6 +1637,636 @@ kernel_del_vtep (vni_t vni, struct interface *ifp, struct in_addr *vtep_ip)
|
||||
return netlink_vxlan_flood_list_update (ifp, vtep_ip, RTM_DELNEIGH);
|
||||
}
|
||||
|
||||
#ifndef NDA_RTA
|
||||
#define NDA_RTA(r) \
|
||||
((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg))))
|
||||
#endif
|
||||
|
||||
static int
|
||||
netlink_macfdb_change (struct sockaddr_nl *snl, struct nlmsghdr *h, int len)
|
||||
{
|
||||
struct ndmsg *ndm;
|
||||
struct interface *ifp;
|
||||
struct zebra_if *zif;
|
||||
struct zebra_vrf *zvrf;
|
||||
struct rtattr *tb[NDA_MAX + 1];
|
||||
struct interface *br_if;
|
||||
struct ethaddr mac;
|
||||
vlanid_t vid = 0;
|
||||
struct prefix vtep_ip;
|
||||
int vid_present = 0, dst_present = 0;
|
||||
char buf[ETHER_ADDR_STRLEN];
|
||||
char vid_buf[20];
|
||||
char dst_buf[30];
|
||||
|
||||
ndm = NLMSG_DATA (h);
|
||||
|
||||
/* The interface should exist. */
|
||||
ifp = if_lookup_by_index_per_ns (zebra_ns_lookup (NS_DEFAULT), ndm->ndm_ifindex);
|
||||
if (!ifp)
|
||||
return 0;
|
||||
|
||||
/* Locate VRF corresponding to interface. We only process MAC notifications
|
||||
* if EVPN is enabled on this VRF.
|
||||
*/
|
||||
zvrf = vrf_info_lookup(ifp->vrf_id);
|
||||
if (!zvrf || !EVPN_ENABLED(zvrf))
|
||||
return 0;
|
||||
if (!ifp->info)
|
||||
return 0;
|
||||
|
||||
/* The interface should be something we're interested in. */
|
||||
if (!IS_ZEBRA_IF_BRIDGE_SLAVE(ifp))
|
||||
return 0;
|
||||
|
||||
/* Drop "permanent" entries. */
|
||||
if (ndm->ndm_state & NUD_PERMANENT)
|
||||
return 0;
|
||||
|
||||
zif = (struct zebra_if *)ifp->info;
|
||||
if ((br_if = zif->brslave_info.br_if) == NULL)
|
||||
{
|
||||
zlog_warn ("%s family %s IF %s(%u) brIF %u - no bridge master",
|
||||
nl_msg_type_to_str (h->nlmsg_type),
|
||||
nl_family_to_str (ndm->ndm_family),
|
||||
ifp->name, ndm->ndm_ifindex,
|
||||
zif->brslave_info.bridge_ifindex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Parse attributes and extract fields of interest. */
|
||||
memset (tb, 0, sizeof tb);
|
||||
netlink_parse_rtattr (tb, NDA_MAX, NDA_RTA (ndm), len);
|
||||
|
||||
if (!tb[NDA_LLADDR])
|
||||
{
|
||||
zlog_warn ("%s family %s IF %s(%u) brIF %u - no LLADDR",
|
||||
nl_msg_type_to_str (h->nlmsg_type),
|
||||
nl_family_to_str (ndm->ndm_family),
|
||||
ifp->name, ndm->ndm_ifindex,
|
||||
zif->brslave_info.bridge_ifindex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (RTA_PAYLOAD (tb[NDA_LLADDR]) != ETHER_ADDR_LEN)
|
||||
{
|
||||
zlog_warn ("%s family %s IF %s(%u) brIF %u - LLADDR is not MAC, len %ld",
|
||||
nl_msg_type_to_str (h->nlmsg_type),
|
||||
nl_family_to_str (ndm->ndm_family),
|
||||
ifp->name, ndm->ndm_ifindex,
|
||||
zif->brslave_info.bridge_ifindex,
|
||||
RTA_PAYLOAD (tb[NDA_LLADDR]));
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy (&mac, RTA_DATA (tb[NDA_LLADDR]), ETHER_ADDR_LEN);
|
||||
|
||||
if ((NDA_VLAN <= NDA_MAX) && tb[NDA_VLAN])
|
||||
{
|
||||
vid_present = 1;
|
||||
vid = *(u_int16_t *) RTA_DATA(tb[NDA_VLAN]);
|
||||
sprintf (vid_buf, " VLAN %u", vid);
|
||||
}
|
||||
|
||||
if (tb[NDA_DST])
|
||||
{
|
||||
/* TODO: Only IPv4 supported now. */
|
||||
dst_present = 1;
|
||||
vtep_ip.family = AF_INET;
|
||||
vtep_ip.prefixlen = IPV4_MAX_BITLEN;
|
||||
memcpy (&(vtep_ip.u.prefix4.s_addr), RTA_DATA (tb[NDA_DST]), IPV4_MAX_BYTELEN);
|
||||
sprintf (dst_buf, " dst %s", inet_ntoa (vtep_ip.u.prefix4));
|
||||
}
|
||||
|
||||
if (IS_ZEBRA_DEBUG_KERNEL)
|
||||
zlog_debug ("Rx %s family %s IF %s(%u)%s MAC %s%s",
|
||||
nl_msg_type_to_str (h->nlmsg_type),
|
||||
nl_family_to_str (ndm->ndm_family),
|
||||
ifp->name, ndm->ndm_ifindex,
|
||||
vid_present ? vid_buf : "",
|
||||
prefix_mac2str (&mac, buf, sizeof (buf)),
|
||||
dst_present ? dst_buf: "");
|
||||
|
||||
if (filter_vlan && vid != filter_vlan)
|
||||
return 0;
|
||||
|
||||
/* If add or update, do accordingly if learnt on a "local" interface; if
|
||||
* the notification is over VxLAN, this has to be related to multi-homing,
|
||||
* so perform an implicit delete of any local entry (if it exists).
|
||||
*/
|
||||
if (h->nlmsg_type == RTM_NEWNEIGH)
|
||||
{
|
||||
/* Drop "permanent" entries. */
|
||||
if (ndm->ndm_state & NUD_PERMANENT)
|
||||
return 0;
|
||||
|
||||
if (IS_ZEBRA_IF_VXLAN(ifp))
|
||||
return zebra_vxlan_check_del_local_mac (ifp, br_if, &mac, vid);
|
||||
|
||||
return zebra_vxlan_local_mac_add_update (ifp, br_if, &mac, vid);
|
||||
}
|
||||
|
||||
/* This is a delete notification.
|
||||
* 1. For a MAC over VxLan, check if it needs to be refreshed(readded)
|
||||
* 2. For a MAC over "local" interface, delete the mac
|
||||
* Note: We will get notifications from both bridge driver and VxLAN driver.
|
||||
* Ignore the notification from VxLan driver as it is also generated
|
||||
* when mac moves from remote to local.
|
||||
*/
|
||||
if (dst_present)
|
||||
return 0;
|
||||
|
||||
if (IS_ZEBRA_IF_VXLAN(ifp))
|
||||
return zebra_vxlan_check_readd_remote_mac (ifp, br_if, &mac, vid);
|
||||
|
||||
return zebra_vxlan_local_mac_del (ifp, br_if, &mac, vid);
|
||||
}
|
||||
|
||||
static int
|
||||
netlink_macfdb_table (struct sockaddr_nl *snl, struct nlmsghdr *h,
|
||||
ns_id_t ns_id, int startup)
|
||||
{
|
||||
int len;
|
||||
struct ndmsg *ndm;
|
||||
|
||||
if (h->nlmsg_type != RTM_NEWNEIGH)
|
||||
return 0;
|
||||
|
||||
/* Length validity. */
|
||||
len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ndmsg));
|
||||
if (len < 0)
|
||||
return -1;
|
||||
|
||||
/* We are interested only in AF_BRIDGE notifications. */
|
||||
ndm = NLMSG_DATA (h);
|
||||
if (ndm->ndm_family != AF_BRIDGE)
|
||||
return 0;
|
||||
|
||||
return netlink_macfdb_change (snl, h, len);
|
||||
}
|
||||
|
||||
/* Request for MAC FDB information from the kernel */
|
||||
static int
|
||||
netlink_request_macs (struct zebra_ns *zns, int family, int type,
|
||||
ifindex_t master_ifindex)
|
||||
{
|
||||
struct
|
||||
{
|
||||
struct nlmsghdr n;
|
||||
struct ifinfomsg ifm;
|
||||
char buf[256];
|
||||
} req;
|
||||
|
||||
/* Form the request, specifying filter (rtattr) if needed. */
|
||||
memset (&req, 0, sizeof (req));
|
||||
req.n.nlmsg_type = type;
|
||||
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
|
||||
req.ifm.ifi_family = family;
|
||||
if (master_ifindex)
|
||||
addattr32 (&req.n, sizeof(req), IFLA_MASTER, master_ifindex);
|
||||
|
||||
return netlink_request (&zns->netlink_cmd, &req.n);
|
||||
}
|
||||
|
||||
/*
|
||||
* MAC forwarding database read using netlink interface. This is invoked
|
||||
* at startup.
|
||||
*/
|
||||
int
|
||||
netlink_macfdb_read (struct zebra_ns *zns)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Get bridge FDB table. */
|
||||
ret = netlink_request_macs (zns, AF_BRIDGE, RTM_GETNEIGH, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
/* We are reading entire table. */
|
||||
filter_vlan = 0;
|
||||
ret = netlink_parse_info (netlink_macfdb_table, &zns->netlink_cmd, zns, 0, 1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* MAC forwarding database read using netlink interface. This is for a
|
||||
* specific bridge and matching specific access VLAN (if VLAN-aware bridge).
|
||||
*/
|
||||
int
|
||||
netlink_macfdb_read_for_bridge (struct zebra_ns *zns, struct interface *ifp,
|
||||
struct interface *br_if)
|
||||
{
|
||||
struct zebra_if *br_zif;
|
||||
struct zebra_if *zif;
|
||||
struct zebra_l2info_vxlan *vxl;
|
||||
int ret = 0;
|
||||
|
||||
|
||||
/* Save VLAN we're filtering on, if needed. */
|
||||
br_zif = (struct zebra_if *) br_if->info;
|
||||
zif = (struct zebra_if *) ifp->info;
|
||||
vxl = &zif->l2info.vxl;
|
||||
if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif))
|
||||
filter_vlan = vxl->access_vlan;
|
||||
|
||||
/* Get bridge FDB table for specific bridge - we do the VLAN filtering. */
|
||||
ret = netlink_request_macs (zns, AF_BRIDGE, RTM_GETNEIGH, br_if->ifindex);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = netlink_parse_info (netlink_macfdb_table, &zns->netlink_cmd, zns, 0, 0);
|
||||
|
||||
/* Reset VLAN filter. */
|
||||
filter_vlan = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
netlink_macfdb_update (struct interface *ifp, vlanid_t vid,
|
||||
struct ethaddr *mac,
|
||||
struct in_addr vtep_ip,
|
||||
int local, int cmd)
|
||||
{
|
||||
struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT);
|
||||
struct
|
||||
{
|
||||
struct nlmsghdr n;
|
||||
struct ndmsg ndm;
|
||||
char buf[256];
|
||||
} req;
|
||||
int dst_alen;
|
||||
struct zebra_if *zif;
|
||||
struct interface *br_if;
|
||||
struct zebra_if *br_zif;
|
||||
char buf[ETHER_ADDR_STRLEN];
|
||||
int vid_present = 0, dst_present = 0;
|
||||
char vid_buf[20];
|
||||
char dst_buf[30];
|
||||
|
||||
zif = ifp->info;
|
||||
if ((br_if = zif->brslave_info.br_if) == NULL)
|
||||
{
|
||||
zlog_warn ("MAC %s on IF %s(%u) - no mapping to bridge",
|
||||
(cmd == RTM_NEWNEIGH) ? "add" : "del",
|
||||
ifp->name, ifp->ifindex);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&req.n, 0, sizeof(req.n));
|
||||
memset(&req.ndm, 0, sizeof(req.ndm));
|
||||
|
||||
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
|
||||
req.n.nlmsg_flags = NLM_F_REQUEST;
|
||||
if (cmd == RTM_NEWNEIGH)
|
||||
req.n.nlmsg_flags |= (NLM_F_CREATE | NLM_F_REPLACE);
|
||||
req.n.nlmsg_type = cmd;
|
||||
req.ndm.ndm_family = AF_BRIDGE;
|
||||
req.ndm.ndm_flags |= NTF_SELF | NTF_MASTER;
|
||||
req.ndm.ndm_state = NUD_REACHABLE;
|
||||
|
||||
req.ndm.ndm_flags |= NTF_EXT_LEARNED;
|
||||
|
||||
addattr_l (&req.n, sizeof (req), NDA_LLADDR, mac, 6);
|
||||
req.ndm.ndm_ifindex = ifp->ifindex;
|
||||
if (!local)
|
||||
{
|
||||
dst_alen = 4; // TODO: hardcoded
|
||||
addattr_l (&req.n, sizeof (req), NDA_DST, &vtep_ip, dst_alen);
|
||||
dst_present = 1;
|
||||
sprintf (dst_buf, " dst %s", inet_ntoa (vtep_ip));
|
||||
}
|
||||
br_zif = (struct zebra_if *) br_if->info;
|
||||
if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif) && vid > 0)
|
||||
{
|
||||
addattr16 (&req.n, sizeof (req), NDA_VLAN, vid);
|
||||
vid_present = 1;
|
||||
sprintf (vid_buf, " VLAN %u", vid);
|
||||
}
|
||||
addattr32 (&req.n, sizeof (req), NDA_MASTER, br_if->ifindex);
|
||||
|
||||
if (IS_ZEBRA_DEBUG_KERNEL)
|
||||
zlog_debug ("Tx %s family %s IF %s(%u)%s MAC %s%s",
|
||||
nl_msg_type_to_str (cmd),
|
||||
nl_family_to_str (req.ndm.ndm_family),
|
||||
ifp->name, ifp->ifindex,
|
||||
vid_present ? vid_buf : "",
|
||||
prefix_mac2str (mac, buf, sizeof (buf)),
|
||||
dst_present ? dst_buf : "");
|
||||
|
||||
return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, 0);
|
||||
}
|
||||
|
||||
#define NUD_VALID (NUD_PERMANENT | NUD_NOARP | NUD_REACHABLE | \
|
||||
NUD_PROBE | NUD_STALE | NUD_DELAY)
|
||||
|
||||
static int
|
||||
netlink_ipneigh_change (struct sockaddr_nl *snl, struct nlmsghdr *h, int len)
|
||||
{
|
||||
struct ndmsg *ndm;
|
||||
struct interface *ifp;
|
||||
struct zebra_if *zif;
|
||||
struct zebra_vrf *zvrf;
|
||||
struct rtattr *tb[NDA_MAX + 1];
|
||||
struct interface *link_if;
|
||||
struct ethaddr mac;
|
||||
struct ipaddr ip;
|
||||
char buf[ETHER_ADDR_STRLEN];
|
||||
char buf2[INET6_ADDRSTRLEN];
|
||||
int mac_present = 0;
|
||||
u_char ext_learned;
|
||||
|
||||
ndm = NLMSG_DATA (h);
|
||||
|
||||
/* The interface should exist. */
|
||||
ifp = if_lookup_by_index_per_ns (zebra_ns_lookup (NS_DEFAULT), ndm->ndm_ifindex);
|
||||
if (!ifp)
|
||||
return 0;
|
||||
|
||||
/* Locate VRF corresponding to interface. We only process neigh notifications
|
||||
* if EVPN is enabled on this VRF.
|
||||
*/
|
||||
zvrf = vrf_info_lookup(ifp->vrf_id);
|
||||
if (!zvrf || !EVPN_ENABLED(zvrf))
|
||||
return 0;
|
||||
if (!ifp->info)
|
||||
return 0;
|
||||
|
||||
/* Drop "permanent" entries. */
|
||||
if (ndm->ndm_state & NUD_PERMANENT)
|
||||
return 0;
|
||||
|
||||
zif = (struct zebra_if *)ifp->info;
|
||||
/* The neighbor is present on an SVI. From this, we locate the underlying
|
||||
* bridge because we're only interested in neighbors on a VxLAN bridge.
|
||||
* The bridge is located based on the nature of the SVI:
|
||||
* (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
|
||||
* and is linked to the bridge
|
||||
* (b) In the case of a VLAN-unaware bridge, the SVI is the bridge inteface
|
||||
* itself
|
||||
*/
|
||||
if (IS_ZEBRA_IF_VLAN(ifp))
|
||||
{
|
||||
link_if = zif->link;
|
||||
if (!link_if)
|
||||
return 0;
|
||||
}
|
||||
else if (IS_ZEBRA_IF_BRIDGE(ifp))
|
||||
link_if = ifp;
|
||||
else
|
||||
return 0;
|
||||
|
||||
/* Parse attributes and extract fields of interest. */
|
||||
memset (tb, 0, sizeof tb);
|
||||
netlink_parse_rtattr (tb, NDA_MAX, NDA_RTA (ndm), len);
|
||||
|
||||
if (!tb[NDA_DST])
|
||||
{
|
||||
zlog_warn ("%s family %s IF %s(%u) - no DST",
|
||||
nl_msg_type_to_str (h->nlmsg_type),
|
||||
nl_family_to_str (ndm->ndm_family),
|
||||
ifp->name, ndm->ndm_ifindex);
|
||||
return 0;
|
||||
}
|
||||
memset (&mac, 0, sizeof (struct ethaddr));
|
||||
memset (&ip, 0, sizeof (struct ipaddr));
|
||||
ip.ipa_type = (ndm->ndm_family == AF_INET) ? IPADDR_V4 : IPADDR_V6;
|
||||
memcpy (&ip.ip.addr, RTA_DATA(tb[NDA_DST]), RTA_PAYLOAD(tb[NDA_DST]));
|
||||
|
||||
if (h->nlmsg_type == RTM_NEWNEIGH)
|
||||
{
|
||||
if (tb[NDA_LLADDR])
|
||||
{
|
||||
if (RTA_PAYLOAD (tb[NDA_LLADDR]) != ETHER_ADDR_LEN)
|
||||
{
|
||||
zlog_warn ("%s family %s IF %s(%u) - LLADDR is not MAC, len %ld",
|
||||
nl_msg_type_to_str (h->nlmsg_type),
|
||||
nl_family_to_str (ndm->ndm_family),
|
||||
ifp->name, ndm->ndm_ifindex,
|
||||
RTA_PAYLOAD (tb[NDA_LLADDR]));
|
||||
return 0;
|
||||
}
|
||||
|
||||
mac_present = 1;
|
||||
memcpy (&mac, RTA_DATA (tb[NDA_LLADDR]), ETHER_ADDR_LEN);
|
||||
}
|
||||
|
||||
ext_learned = (ndm->ndm_flags & NTF_EXT_LEARNED) ? 1 : 0;
|
||||
|
||||
if (IS_ZEBRA_DEBUG_KERNEL)
|
||||
zlog_debug ("Rx %s family %s IF %s(%u) IP %s MAC %s state 0x%x flags 0x%x",
|
||||
nl_msg_type_to_str (h->nlmsg_type),
|
||||
nl_family_to_str (ndm->ndm_family),
|
||||
ifp->name, ndm->ndm_ifindex,
|
||||
ipaddr2str (&ip, buf2, sizeof(buf2)),
|
||||
mac_present ? prefix_mac2str (&mac, buf, sizeof (buf)) : "",
|
||||
ndm->ndm_state, ndm->ndm_flags);
|
||||
|
||||
/* If the neighbor state is valid for use, process as an add or update
|
||||
* else process as a delete. Note that the delete handling may result
|
||||
* in re-adding the neighbor if it is a valid "remote" neighbor.
|
||||
*/
|
||||
if (ndm->ndm_state & NUD_VALID)
|
||||
return zebra_vxlan_local_neigh_add_update (ifp, link_if,
|
||||
&ip, &mac,
|
||||
ndm->ndm_state, ext_learned);
|
||||
|
||||
return zebra_vxlan_local_neigh_del (ifp, link_if, &ip);
|
||||
}
|
||||
|
||||
if (IS_ZEBRA_DEBUG_KERNEL)
|
||||
zlog_debug ("Rx %s family %s IF %s(%u) IP %s",
|
||||
nl_msg_type_to_str (h->nlmsg_type),
|
||||
nl_family_to_str (ndm->ndm_family),
|
||||
ifp->name, ndm->ndm_ifindex,
|
||||
ipaddr2str (&ip, buf2, sizeof(buf2)));
|
||||
|
||||
/* Process the delete - it may result in re-adding the neighbor if it is
|
||||
* a valid "remote" neighbor.
|
||||
*/
|
||||
return zebra_vxlan_local_neigh_del (ifp, link_if, &ip);
|
||||
}
|
||||
|
||||
static int
|
||||
netlink_neigh_table (struct sockaddr_nl *snl, struct nlmsghdr *h,
|
||||
ns_id_t ns_id, int startup)
|
||||
{
|
||||
int len;
|
||||
struct ndmsg *ndm;
|
||||
|
||||
if (h->nlmsg_type != RTM_NEWNEIGH)
|
||||
return 0;
|
||||
|
||||
/* Length validity. */
|
||||
len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ndmsg));
|
||||
if (len < 0)
|
||||
return -1;
|
||||
|
||||
/* We are interested only in AF_INET or AF_INET6 notifications. */
|
||||
ndm = NLMSG_DATA (h);
|
||||
if (ndm->ndm_family != AF_INET && ndm->ndm_family != AF_INET6)
|
||||
return 0;
|
||||
|
||||
return netlink_neigh_change (snl, h, len);
|
||||
}
|
||||
|
||||
/* Request for IP neighbor information from the kernel */
|
||||
static int
|
||||
netlink_request_neigh (struct zebra_ns *zns, int family, int type,
|
||||
ifindex_t ifindex)
|
||||
{
|
||||
struct
|
||||
{
|
||||
struct nlmsghdr n;
|
||||
struct ndmsg ndm;
|
||||
char buf[256];
|
||||
} req;
|
||||
|
||||
/* Form the request, specifying filter (rtattr) if needed. */
|
||||
memset (&req, 0, sizeof (req));
|
||||
req.n.nlmsg_type = type;
|
||||
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
|
||||
req.ndm.ndm_family = family;
|
||||
if (ifindex)
|
||||
addattr32 (&req.n, sizeof(req), NDA_IFINDEX, ifindex);
|
||||
|
||||
return netlink_request (&zns->netlink_cmd, &req.n);
|
||||
}
|
||||
|
||||
/*
|
||||
* IP Neighbor table read using netlink interface. This is invoked
|
||||
* at startup.
|
||||
*/
|
||||
int
|
||||
netlink_neigh_read (struct zebra_ns *zns)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Get IP neighbor table. */
|
||||
ret = netlink_request_neigh (zns, AF_UNSPEC, RTM_GETNEIGH, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = netlink_parse_info (netlink_neigh_table, &zns->netlink_cmd, zns, 0, 1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* IP Neighbor table read using netlink interface. This is for a specific
|
||||
* VLAN device.
|
||||
*/
|
||||
int
|
||||
netlink_neigh_read_for_vlan (struct zebra_ns *zns, struct interface *vlan_if)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = netlink_request_neigh (zns, AF_UNSPEC, RTM_GETNEIGH, vlan_if->ifindex);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = netlink_parse_info (netlink_neigh_table, &zns->netlink_cmd, zns, 0, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
netlink_neigh_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
|
||||
ns_id_t ns_id)
|
||||
{
|
||||
int len;
|
||||
struct ndmsg *ndm;
|
||||
|
||||
if (!(h->nlmsg_type == RTM_NEWNEIGH || h->nlmsg_type == RTM_DELNEIGH))
|
||||
return 0;
|
||||
|
||||
/* Length validity. */
|
||||
len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ndmsg));
|
||||
if (len < 0)
|
||||
return -1;
|
||||
|
||||
/* Is this a notification for the MAC FDB or IP neighbor table? */
|
||||
ndm = NLMSG_DATA (h);
|
||||
if (ndm->ndm_family == AF_BRIDGE)
|
||||
return netlink_macfdb_change (snl, h, len);
|
||||
|
||||
if (ndm->ndm_type != RTN_UNICAST)
|
||||
return 0;
|
||||
|
||||
if (ndm->ndm_family == AF_INET || ndm->ndm_family == AF_INET6)
|
||||
return netlink_ipneigh_change (snl, h, len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
netlink_neigh_update2 (struct interface *ifp, struct ipaddr *ip,
|
||||
struct ethaddr *mac, u_int32_t flags, int cmd)
|
||||
{
|
||||
struct {
|
||||
struct nlmsghdr n;
|
||||
struct ndmsg ndm;
|
||||
char buf[256];
|
||||
} req;
|
||||
int ipa_len;
|
||||
|
||||
struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT);
|
||||
char buf[INET6_ADDRSTRLEN];
|
||||
char buf2[ETHER_ADDR_STRLEN];
|
||||
|
||||
memset(&req.n, 0, sizeof(req.n));
|
||||
memset(&req.ndm, 0, sizeof(req.ndm));
|
||||
|
||||
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
|
||||
req.n.nlmsg_flags = NLM_F_REQUEST;
|
||||
if (cmd == RTM_NEWNEIGH)
|
||||
req.n.nlmsg_flags |= (NLM_F_CREATE | NLM_F_REPLACE);
|
||||
req.n.nlmsg_type = cmd; //RTM_NEWNEIGH or RTM_DELNEIGH
|
||||
req.ndm.ndm_family = IS_IPADDR_V4(ip) ? AF_INET : AF_INET6;
|
||||
req.ndm.ndm_state = flags;
|
||||
req.ndm.ndm_ifindex = ifp->ifindex;
|
||||
req.ndm.ndm_type = RTN_UNICAST;
|
||||
req.ndm.ndm_flags = NTF_EXT_LEARNED;
|
||||
|
||||
|
||||
ipa_len = IS_IPADDR_V4(ip) ? IPV4_MAX_BYTELEN : IPV6_MAX_BYTELEN;
|
||||
addattr_l(&req.n, sizeof(req), NDA_DST, &ip->ip.addr, ipa_len);
|
||||
if (mac)
|
||||
addattr_l (&req.n, sizeof (req), NDA_LLADDR, mac, 6);
|
||||
|
||||
if (IS_ZEBRA_DEBUG_KERNEL)
|
||||
zlog_debug ("Tx %s family %s IF %s(%u) Neigh %s MAC %s",
|
||||
nl_msg_type_to_str (cmd),
|
||||
nl_family_to_str (req.ndm.ndm_family),
|
||||
ifp->name, ifp->ifindex,
|
||||
ipaddr2str (ip, buf, sizeof(buf)),
|
||||
mac ? prefix_mac2str (mac, buf2, sizeof (buf2)) : "null");
|
||||
|
||||
return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, 0);
|
||||
}
|
||||
|
||||
int
|
||||
kernel_add_mac (struct interface *ifp, vlanid_t vid,
|
||||
struct ethaddr *mac, struct in_addr vtep_ip)
|
||||
{
|
||||
return netlink_macfdb_update (ifp, vid, mac, vtep_ip, 0, RTM_NEWNEIGH);
|
||||
}
|
||||
|
||||
int
|
||||
kernel_del_mac (struct interface *ifp, vlanid_t vid,
|
||||
struct ethaddr *mac, struct in_addr vtep_ip, int local)
|
||||
{
|
||||
return netlink_macfdb_update (ifp, vid, mac, vtep_ip, local, RTM_DELNEIGH);
|
||||
}
|
||||
|
||||
int kernel_add_neigh (struct interface *ifp, struct ipaddr *ip,
|
||||
struct ethaddr *mac)
|
||||
{
|
||||
return netlink_neigh_update2 (ifp, ip, mac, NUD_REACHABLE,
|
||||
RTM_NEWNEIGH);
|
||||
}
|
||||
|
||||
int kernel_del_neigh (struct interface *ifp, struct ipaddr *ip)
|
||||
{
|
||||
return netlink_neigh_update2 (ifp, ip, NULL, 0, RTM_DELNEIGH);
|
||||
}
|
||||
|
||||
/*
|
||||
* MPLS label forwarding table change via netlink interface.
|
||||
*/
|
||||
|
@ -51,6 +51,15 @@ extern int netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
|
||||
ns_id_t ns_id, int startup);
|
||||
extern int netlink_route_read (struct zebra_ns *zns);
|
||||
|
||||
extern int netlink_neigh_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
|
||||
ns_id_t ns_id);
|
||||
extern int netlink_macfdb_read (struct zebra_ns *zns);
|
||||
extern int netlink_macfdb_read_for_bridge (struct zebra_ns *zns,
|
||||
struct interface *ifp, struct interface *br_if);
|
||||
extern int netlink_neigh_read (struct zebra_ns *zns);
|
||||
extern int netlink_neigh_read_for_vlan (struct zebra_ns *zns,
|
||||
struct interface *vlan_if);
|
||||
|
||||
#endif /* HAVE_NETLINK */
|
||||
|
||||
#endif /* _ZEBRA_RT_NETLINK_H */
|
||||
|
@ -441,3 +441,28 @@ kernel_del_vtep (vni_t vni, struct interface *ifp, struct in_addr *vtep_ip)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
kernel_add_mac (struct interface *ifp, vlanid_t vid,
|
||||
struct ethaddr *mac, struct in_addr vtep_ip)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
kernel_del_mac (struct interface *ifp, vlanid_t vid,
|
||||
struct ethaddr *mac, struct in_addr vtep_ip, int local)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kernel_add_neigh (struct interface *ifp, struct ipaddr *ip,
|
||||
struct ethaddr *mac)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kernel_del_neigh (struct interface *ifp, struct ipaddr *ip)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -237,3 +237,23 @@ route_read (struct zebra_ns *zns)
|
||||
exit:
|
||||
close (dev);
|
||||
}
|
||||
|
||||
/* Only implemented for netlink method */
|
||||
void
|
||||
macfdb_read (struct zebra_ns *zns)
|
||||
{
|
||||
}
|
||||
|
||||
void macfdb_read_for_bridge (struct zebra_ns *zns, struct interface *ifp,
|
||||
struct interface *br_if)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
neigh_read (struct zebra_ns *zns)
|
||||
{
|
||||
}
|
||||
|
||||
void neigh_read_for_vlan (struct zebra_ns *zns, struct interface *vlan_if)
|
||||
{
|
||||
}
|
||||
|
@ -29,3 +29,24 @@ void route_read (struct zebra_ns *zns)
|
||||
{
|
||||
netlink_route_read (zns);
|
||||
}
|
||||
|
||||
void macfdb_read (struct zebra_ns *zns)
|
||||
{
|
||||
netlink_macfdb_read (zns);
|
||||
}
|
||||
|
||||
void macfdb_read_for_bridge (struct zebra_ns *zns, struct interface *ifp,
|
||||
struct interface *br_if)
|
||||
{
|
||||
netlink_macfdb_read_for_bridge (zns, ifp, br_if);
|
||||
}
|
||||
|
||||
void neigh_read (struct zebra_ns *zns)
|
||||
{
|
||||
netlink_neigh_read (zns);
|
||||
}
|
||||
|
||||
void neigh_read_for_vlan (struct zebra_ns *zns, struct interface *vlan_if)
|
||||
{
|
||||
netlink_neigh_read_for_vlan (zns, vlan_if);
|
||||
}
|
||||
|
@ -83,3 +83,23 @@ route_read (struct zebra_ns *zns)
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Only implemented for the netlink method. */
|
||||
void
|
||||
macfdb_read (struct zebra_ns *zns)
|
||||
{
|
||||
}
|
||||
|
||||
void macfdb_read_for_bridge (struct zebra_ns *zns, struct interface *ifp,
|
||||
struct interface *br_if)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
neigh_read (struct zebra_ns *zns)
|
||||
{
|
||||
}
|
||||
|
||||
void neigh_read_for_vlan (struct zebra_ns *zns, struct interface *vlan_if)
|
||||
{
|
||||
}
|
||||
|
1815
zebra/zebra_vxlan.c
1815
zebra/zebra_vxlan.c
File diff suppressed because it is too large
Load Diff
@ -42,6 +42,33 @@
|
||||
#define ZEBRA_VXLIF_MASTER_CHANGE 0x2
|
||||
#define ZEBRA_VXLIF_VLAN_CHANGE 0x4
|
||||
|
||||
extern int zebra_vxlan_svi_up (struct interface *ifp, struct interface *link_if);
|
||||
extern int zebra_vxlan_svi_down (struct interface *ifp, struct interface *link_if);
|
||||
extern int zebra_vxlan_local_neigh_add_update (struct interface *ifp,
|
||||
struct interface *link_if,
|
||||
struct ipaddr *ip,
|
||||
struct ethaddr *macaddr,
|
||||
u_int16_t state,
|
||||
u_char ext_learned);
|
||||
extern int zebra_vxlan_local_neigh_del (struct interface *ifp,
|
||||
struct interface *link_if,
|
||||
struct ipaddr *ip);
|
||||
extern int zebra_vxlan_remote_macip_add (struct zserv *client, int sock,
|
||||
u_short length, struct zebra_vrf *zvrf);
|
||||
extern int zebra_vxlan_remote_macip_del (struct zserv *client, int sock,
|
||||
u_short length, struct zebra_vrf *zvrf);
|
||||
extern int zebra_vxlan_local_mac_add_update (struct interface *ifp,
|
||||
struct interface *br_if,
|
||||
struct ethaddr *mac, vlanid_t vid);
|
||||
extern int zebra_vxlan_local_mac_del (struct interface *ifp,
|
||||
struct interface *br_if,
|
||||
struct ethaddr *mac, vlanid_t vid);
|
||||
extern int zebra_vxlan_check_readd_remote_mac (struct interface *ifp,
|
||||
struct interface *br_if,
|
||||
struct ethaddr *mac, vlanid_t vid);
|
||||
extern int zebra_vxlan_check_del_local_mac (struct interface *ifp,
|
||||
struct interface *br_if,
|
||||
struct ethaddr *mac, vlanid_t vid);
|
||||
extern int zebra_vxlan_if_up (struct interface *ifp);
|
||||
extern int zebra_vxlan_if_down (struct interface *ifp);
|
||||
extern int zebra_vxlan_if_add (struct interface *ifp);
|
||||
|
@ -30,6 +30,56 @@
|
||||
#include "zebra/zebra_l2.h"
|
||||
#include "zebra/zebra_vxlan.h"
|
||||
|
||||
int zebra_vxlan_svi_up (struct interface *ifp, struct interface *link_if)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int zebra_vxlan_svi_down (struct interface *ifp, struct interface *link_if)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int zebra_vxlan_remote_macip_add (struct zserv *client, int sock,
|
||||
u_short length, struct zebra_vrf *zvrf)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int zebra_vxlan_remote_macip_del (struct zserv *client, int sock,
|
||||
u_short length, struct zebra_vrf *zvrf)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int zebra_vxlan_local_mac_add_update (struct interface *ifp,
|
||||
struct interface *br_if,
|
||||
struct ethaddr *mac, vlanid_t vid)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int zebra_vxlan_local_mac_del (struct interface *ifp,
|
||||
struct interface *br_if,
|
||||
struct ethaddr *mac, vlanid_t vid)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int zebra_vxlan_check_readd_remote_mac (struct interface *ifp,
|
||||
struct interface *br_if,
|
||||
struct ethaddr *mac, vlanid_t vid)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int zebra_vxlan_check_del_local_mac (struct interface *ifp,
|
||||
struct interface *br_if,
|
||||
struct ethaddr *mac, vlanid_t vid)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
zebra_vxlan_if_up (struct interface *ifp)
|
||||
{
|
||||
|
@ -2444,6 +2444,12 @@ zebra_client_read (struct thread *thread)
|
||||
case ZEBRA_REMOTE_VTEP_DEL:
|
||||
zebra_vxlan_remote_vtep_del (client, sock, length, zvrf);
|
||||
break;
|
||||
case ZEBRA_REMOTE_MACIP_ADD:
|
||||
zebra_vxlan_remote_macip_add (client, sock, length, zvrf);
|
||||
break;
|
||||
case ZEBRA_REMOTE_MACIP_DEL:
|
||||
zebra_vxlan_remote_macip_del (client, sock, length, zvrf);
|
||||
break;
|
||||
default:
|
||||
zlog_info ("Zebra received unknown command %d", command);
|
||||
break;
|
||||
@ -2737,6 +2743,9 @@ zebra_show_client_detail (struct vty *vty, struct zserv *client)
|
||||
vty_outln (vty, "Interface Down Notifications: %d",client->ifdown_cnt);
|
||||
vty_outln (vty, "VNI add notifications: %d", client->vniadd_cnt);
|
||||
vty_outln (vty, "VNI delete notifications: %d", client->vnidel_cnt);
|
||||
vty_outln (vty, "MAC-IP add notifications: %d", client->macipadd_cnt);
|
||||
vty_outln (vty, "MAC-IP delete notifications: %d", client->macipdel_cnt);
|
||||
|
||||
vty_out (vty, VTYNL);
|
||||
return;
|
||||
}
|
||||
|
@ -107,6 +107,8 @@ struct zserv
|
||||
u_int32_t bfd_client_reg_cnt;
|
||||
u_int32_t vniadd_cnt;
|
||||
u_int32_t vnidel_cnt;
|
||||
u_int32_t macipadd_cnt;
|
||||
u_int32_t macipdel_cnt;
|
||||
|
||||
time_t connect_time;
|
||||
time_t last_read_time;
|
||||
@ -147,6 +149,11 @@ extern void hostinfo_get (void);
|
||||
extern void rib_init (void);
|
||||
extern void interface_list (struct zebra_ns *);
|
||||
extern void route_read (struct zebra_ns *);
|
||||
extern void macfdb_read (struct zebra_ns *);
|
||||
extern void macfdb_read_for_bridge (struct zebra_ns *, struct interface *,
|
||||
struct interface *);
|
||||
extern void neigh_read (struct zebra_ns *);
|
||||
extern void neigh_read_for_vlan (struct zebra_ns *, struct interface *);
|
||||
extern void kernel_init (struct zebra_ns *);
|
||||
extern void kernel_terminate (struct zebra_ns *);
|
||||
extern void zebra_route_map_init (void);
|
||||
|
Loading…
Reference in New Issue
Block a user