diff options
Diffstat (limited to 'zebra')
-rw-r--r-- | zebra/interface.c | 7 | ||||
-rw-r--r-- | zebra/rt.h | 5 | ||||
-rw-r--r-- | zebra/rt_netlink.c | 29 | ||||
-rw-r--r-- | zebra/rt_socket.c | 4 | ||||
-rw-r--r-- | zebra/zapi_msg.c | 80 |
5 files changed, 108 insertions, 17 deletions
diff --git a/zebra/interface.c b/zebra/interface.c index 3eeed9ac9..4b708496a 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -898,7 +898,8 @@ void if_nbr_mac_to_ipv4ll_neigh_update(struct interface *ifp, * 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); + kernel_neigh_update(0, ifp->ifindex, (void *)&ipv4_ll.s_addr, mac, 6, + ns_id, AF_INET, true); /* Add new neighbor entry. * @@ -910,8 +911,8 @@ void if_nbr_mac_to_ipv4ll_neigh_update(struct interface *ifp, * they'll be useless to us. */ if (add) - kernel_neigh_update(add, ifp->ifindex, ipv4_ll.s_addr, mac, 6, - ns_id); + kernel_neigh_update(add, ifp->ifindex, (void *)&ipv4_ll.s_addr, + mac, 6, ns_id, AF_INET, true); memcpy(&zif->neigh_mac[0], &mac[0], 6); diff --git a/zebra/rt.h b/zebra/rt.h index 00ff37875..f79ddbe95 100644 --- a/zebra/rt.h +++ b/zebra/rt.h @@ -68,8 +68,9 @@ kernel_pbr_rule_update(struct zebra_dplane_ctx *ctx); #endif /* !HAVE_NETLINK */ -extern int kernel_neigh_update(int cmd, int ifindex, uint32_t addr, char *lla, - int llalen, ns_id_t ns_id); +extern int kernel_neigh_update(int cmd, int ifindex, void *addr, char *lla, + int llalen, ns_id_t ns_id, uint8_t family, + bool permanent); extern int kernel_neigh_register(vrf_id_t vrf_id, struct zserv *client, bool reg); extern int kernel_interface_set_master(struct interface *master, diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 82ef78d29..be9c91367 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -1537,10 +1537,10 @@ static void _netlink_mpls_debug(int cmd, uint32_t label, const char *routedesc) routedesc, nl_msg_type_to_str(cmd), label); } -static int netlink_neigh_update(int cmd, int ifindex, uint32_t addr, char *lla, - int llalen, ns_id_t ns_id) +static int netlink_neigh_update(int cmd, int ifindex, void *addr, char *lla, + int llalen, ns_id_t ns_id, uint8_t family, + bool permanent, uint8_t protocol) { - uint8_t protocol = RTPROT_ZEBRA; struct { struct nlmsghdr n; struct ndmsg ndm; @@ -1556,15 +1556,23 @@ static int netlink_neigh_update(int cmd, int ifindex, uint32_t addr, char *lla, req.n.nlmsg_type = cmd; // RTM_NEWNEIGH or RTM_DELNEIGH req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid; - req.ndm.ndm_family = AF_INET; - req.ndm.ndm_state = NUD_PERMANENT; + req.ndm.ndm_family = family; req.ndm.ndm_ifindex = ifindex; req.ndm.ndm_type = RTN_UNICAST; + if (cmd == RTM_NEWNEIGH) { + if (!permanent) + req.ndm.ndm_state = NUD_REACHABLE; + else + req.ndm.ndm_state = NUD_PERMANENT; + } else + req.ndm.ndm_state = NUD_FAILED; nl_attr_put(&req.n, sizeof(req), NDA_PROTOCOL, &protocol, sizeof(protocol)); - nl_attr_put32(&req.n, sizeof(req), NDA_DST, addr); - nl_attr_put(&req.n, sizeof(req), NDA_LLADDR, lla, llalen); + req.ndm.ndm_type = RTN_UNICAST; + nl_attr_put32(&req.n, family2addrsize(family), NDA_DST, addr); + if (lla) + nl_attr_put(&req.n, sizeof(req), NDA_LLADDR, lla, llalen); return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, 0); @@ -2679,11 +2687,12 @@ int netlink_nexthop_read(struct zebra_ns *zns) } -int kernel_neigh_update(int add, int ifindex, uint32_t addr, char *lla, - int llalen, ns_id_t ns_id) +int kernel_neigh_update(int add, int ifindex, void *addr, char *lla, int llalen, + ns_id_t ns_id, uint8_t family, bool permanent) { return netlink_neigh_update(add ? RTM_NEWNEIGH : RTM_DELNEIGH, ifindex, - addr, lla, llalen, ns_id); + addr, lla, llalen, ns_id, family, permanent, + RTPROT_ZEBRA); } /** diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c index 5fdf58962..006513ac9 100644 --- a/zebra/rt_socket.c +++ b/zebra/rt_socket.c @@ -368,8 +368,8 @@ int kernel_neigh_register(vrf_id_t vrf_id, struct zserv *client, bool reg) return 0; } -int kernel_neigh_update(int add, int ifindex, uint32_t addr, char *lla, - int llalen, ns_id_t ns_id) +int kernel_neigh_update(int add, int ifindex, void *addr, char *lla, int llalen, + ns_id_t ns_id, uint8_t family, bool permanent) { /* TODO */ return 0; diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 304a6a03f..909b3b8ac 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -3214,6 +3214,39 @@ stream_failure: return; } +static int zebra_neigh_read_ip(struct stream *s, struct prefix *add) +{ + STREAM_GETC(s, add->family); + if (add->family != AF_INET && add->family != AF_INET6) + return -1; + STREAM_GET(&add->u.prefix, s, family2addrsize(add->family)); + if (add->family == AF_INET) + add->prefixlen = IPV4_MAX_BITLEN; + else + add->prefixlen = IPV6_MAX_BITLEN; + return 0; +stream_failure: + return -1; +} + +static int zebra_neigh_get(struct stream *s, struct zapi_nbr *api, bool add) +{ + int ret; + + ret = zebra_neigh_read_ip(s, &api->pfx_in); + if (ret < 0) + return -1; + if (add) { + ret = zebra_neigh_read_ip(s, &api->pfx_out); + if (ret < 0) + return -1; + } + STREAM_GETL(s, api->index); + return 0; +stream_failure: + return -1; +} + static inline void zebra_neigh_register(ZAPI_HANDLER_ARGS) { afi_t afi; @@ -3246,6 +3279,51 @@ stream_failure: return; } +static inline void zebra_neigh_add(ZAPI_HANDLER_ARGS) +{ + struct stream *s; + struct zapi_nbr api; + int ret; + struct zebra_ns *zns = zvrf->zns; + ns_id_t ns_id; + + if (!zns) + return; + ns_id = zns->ns_id; + + s = msg; + memset(&api, 0, sizeof(api)); + ret = zebra_neigh_get(s, &api, true); + if (ret < 0) + return; + kernel_neigh_update(1, api.index, &api.pfx_in.u.prefix, + (char *)&api.pfx_out.u.prefix, + family2addrsize(api.pfx_out.family), + ns_id, api.pfx_in.family, false, client->proto); +} + +static inline void zebra_neigh_del(ZAPI_HANDLER_ARGS) +{ + struct stream *s; + struct zapi_nbr api; + int ret; + struct zebra_ns *zns = zvrf->zns; + ns_id_t ns_id; + + if (!zns) + return; + ns_id = zns->ns_id; + s = msg; + memset(&api, 0, sizeof(api)); + ret = zebra_neigh_get(s, &api, false); + if (ret < 0) + return; + kernel_neigh_update(0, api.index, &api.pfx_in.u.prefix, + NULL, 0, ns_id, api.pfx_in.family, + true, client->proto); +} + + static inline void zread_iptable(ZAPI_HANDLER_ARGS) { struct zebra_pbr_iptable *zpi = @@ -3431,6 +3509,8 @@ void (*const zserv_handlers[])(ZAPI_HANDLER_ARGS) = { [ZEBRA_ROUTE_NOTIFY_REQUEST] = zread_route_notify_request, [ZEBRA_EVPN_REMOTE_NH_ADD] = zebra_evpn_proc_remote_nh, [ZEBRA_EVPN_REMOTE_NH_DEL] = zebra_evpn_proc_remote_nh, + [ZEBRA_NEIGH_ADD] = zebra_neigh_add, + [ZEBRA_NEIGH_DEL] = zebra_neigh_del, [ZEBRA_NHRP_NEIGH_REGISTER] = zebra_neigh_register, [ZEBRA_NHRP_NEIGH_UNREGISTER] = zebra_neigh_unregister, }; |