summaryrefslogtreecommitdiff
path: root/zebra/rt_netlink.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/rt_netlink.c')
-rw-r--r--zebra/rt_netlink.c94
1 files changed, 56 insertions, 38 deletions
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 3053c56d1e..df53a06bc2 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -397,14 +397,14 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl,
if (IS_ZEBRA_DEBUG_KERNEL) {
char buf[PREFIX_STRLEN];
char buf2[PREFIX_STRLEN];
- zlog_debug("%s %s%s%s vrf %u metric: %d Admin Distance: %d",
+ zlog_debug("%s %s%s%s vrf %u(%u) metric: %d Admin Distance: %d",
nl_msg_type_to_str(h->nlmsg_type),
prefix2str(&p, buf, sizeof(buf)),
src_p.prefixlen ? " from " : "",
src_p.prefixlen
? prefix2str(&src_p, buf2, sizeof(buf2))
: "",
- vrf_id, metric, distance);
+ vrf_id, table, metric, distance);
}
afi_t afi = AFI_IP;
@@ -1253,23 +1253,21 @@ _netlink_mpls_build_multipath(const char *routedesc, zebra_nhlfe_t *nhlfe,
*
* @param cmd: Netlink command which is to be processed
* @param p: Prefix for which the change is due
- * @param nexthop: Nexthop which is currently processed
- * @param routedesc: Semantic annotation for nexthop
- * (recursive, multipath, etc.)
* @param family: Address family which the change concerns
+ * @param zvrf: The vrf we are in
+ * @param tableid: The table we are working on
*/
static void _netlink_route_debug(int cmd, struct prefix *p,
- struct nexthop *nexthop, const char *routedesc,
int family, struct zebra_vrf *zvrf,
uint32_t tableid)
{
if (IS_ZEBRA_DEBUG_KERNEL) {
char buf[PREFIX_STRLEN];
zlog_debug(
- "netlink_route_multipath() (%s): %s %s vrf %u(%u) type %s",
- routedesc, nl_msg_type_to_str(cmd),
- prefix2str(p, buf, sizeof(buf)), zvrf_id(zvrf), tableid,
- (nexthop) ? nexthop_type_to_str(nexthop->type) : "UNK");
+ "netlink_route_multipath(): %s %s vrf %u(%u)",
+ nl_msg_type_to_str(cmd),
+ prefix2str(p, buf, sizeof(buf)),
+ zvrf_id(zvrf), tableid);
}
}
@@ -1321,7 +1319,6 @@ static int netlink_route_multipath(int cmd, struct prefix *p,
struct sockaddr_nl snl;
struct nexthop *nexthop = NULL;
unsigned int nexthop_num;
- int discard = 0;
int family = PREFIX_FAMILY(p);
const char *routedesc;
int setsrc = 0;
@@ -1380,7 +1377,15 @@ static int netlink_route_multipath(int cmd, struct prefix *p,
addattr32(&req.n, sizeof req, RTA_TABLE, re->table);
}
- if (discard)
+ _netlink_route_debug(cmd, p, family, zvrf, re->table);
+
+ /*
+ * If we are not updating the route and we have received
+ * a route delete, then all we need to fill in is the
+ * prefix information to tell the kernel to schwack
+ * it.
+ */
+ if (!update && cmd == RTM_DELROUTE)
goto skip;
if (re->mtu || re->nexthop_mtu) {
@@ -1486,8 +1491,6 @@ static int netlink_route_multipath(int cmd, struct prefix *p,
? "recursive, single-path"
: "single-path";
- _netlink_route_debug(cmd, p, nexthop, routedesc,
- family, zvrf, re->table);
_netlink_route_build_singlepath(
routedesc, bytelen, nexthop, &req.n,
&req.r, sizeof req, cmd);
@@ -1570,8 +1573,6 @@ static int netlink_route_multipath(int cmd, struct prefix *p,
: "multipath";
nexthop_num++;
- _netlink_route_debug(cmd, p, nexthop, routedesc,
- family, zvrf, re->table);
_netlink_route_build_multipath(
routedesc, bytelen, nexthop, rta, rtnh,
&req.r, &src1);
@@ -2112,21 +2113,53 @@ static int netlink_ipneigh_change(struct sockaddr_nl *snl, struct nlmsghdr *h,
ndm = NLMSG_DATA(h);
- /* We only process neigh notifications if EVPN is enabled */
- if (!is_evpn_enabled())
- return 0;
-
/* The interface should exist. */
ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id),
ndm->ndm_ifindex);
if (!ifp || !ifp->info)
return 0;
- /* Drop "permanent" entries. */
- if (ndm->ndm_state & NUD_PERMANENT)
+ zif = (struct zebra_if *)ifp->info;
+
+ /* 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(&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]));
+
+ /* Drop some "permanent" entries. */
+ if (ndm->ndm_state & NUD_PERMANENT) {
+ char buf[16] = "169.254.0.1";
+ struct in_addr ipv4_ll;
+
+ if (ndm->ndm_family != AF_INET)
+ return 0;
+
+ if (!zif->v6_2_v4_ll_neigh_entry)
+ return 0;
+
+ if (h->nlmsg_type != RTM_DELNEIGH)
+ return 0;
+
+ inet_pton(AF_INET, buf, &ipv4_ll);
+ if (ipv4_ll.s_addr != ip.ip._v4_addr.s_addr)
+ return 0;
+
+ if_nbr_ipv6ll_to_ipv4ll_neigh_update(
+ ifp, &zif->v6_2_v4_ll_addr6, true);
+ 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.
@@ -2148,22 +2181,7 @@ static int netlink_ipneigh_change(struct sockaddr_nl *snl, struct nlmsghdr *h,
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]) != ETH_ALEN) {