diff options
-rw-r--r-- | lib/log.c | 4 | ||||
-rw-r--r-- | lib/zclient.h | 13 | ||||
-rw-r--r-- | nhrpd/netlink_arp.c | 23 | ||||
-rw-r--r-- | nhrpd/nhrp_route.c | 26 | ||||
-rw-r--r-- | nhrpd/nhrpd.h | 3 | ||||
-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 |
10 files changed, 154 insertions, 40 deletions
@@ -469,7 +469,9 @@ static const struct zebra_desc_table command_types[] = { DESC_ENTRY(ZEBRA_NHRP_NEIGH_REMOVED), DESC_ENTRY(ZEBRA_NHRP_NEIGH_GET), DESC_ENTRY(ZEBRA_NHRP_NEIGH_REGISTER), - DESC_ENTRY(ZEBRA_NHRP_NEIGH_UNREGISTER)}; + DESC_ENTRY(ZEBRA_NHRP_NEIGH_UNREGISTER), + DESC_ENTRY(ZEBRA_NEIGH_ADD), + DESC_ENTRY(ZEBRA_NEIGH_DEL)}; #undef DESC_ENTRY diff --git a/lib/zclient.h b/lib/zclient.h index d0d77f93c..8d531c53f 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -228,6 +228,8 @@ typedef enum { ZEBRA_NHRP_NEIGH_GET, ZEBRA_NHRP_NEIGH_REGISTER, ZEBRA_NHRP_NEIGH_UNREGISTER, + ZEBRA_NEIGH_ADD, + ZEBRA_NEIGH_DEL, } zebra_message_types_t; enum zebra_error_types { @@ -802,6 +804,17 @@ struct zclient_options { extern struct zclient_options zclient_options_default; +/* link layer representation for GRE like interfaces + * pfx_in is the underlay IP, pfx_out is the tunnel dest + * index stands for the index of the interface + */ +struct zapi_nbr { + int cmd; + struct prefix pfx_in; + struct prefix pfx_out; + ifindex_t index; +}; + /* * We reserve the top 4 bits for l2-NHG, everything else * is for zebra/proto l3-NHG. diff --git a/nhrpd/netlink_arp.c b/nhrpd/netlink_arp.c index bb8e73ab1..bf5d74c25 100644 --- a/nhrpd/netlink_arp.c +++ b/nhrpd/netlink_arp.c @@ -34,28 +34,7 @@ typedef void (*netlink_dispatch_f)(struct nlmsghdr *msg, struct zbuf *zb); void netlink_update_binding(struct interface *ifp, union sockunion *proto, union sockunion *nbma) { - struct nlmsghdr *n; - struct ndmsg *ndm; - struct zbuf *zb = zbuf_alloc(512); - - n = znl_nlmsg_push(zb, nbma ? RTM_NEWNEIGH : RTM_DELNEIGH, - NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE); - ndm = znl_push(zb, sizeof(*ndm)); - *ndm = (struct ndmsg){ - .ndm_family = sockunion_family(proto), - .ndm_ifindex = ifp->ifindex, - .ndm_type = RTN_UNICAST, - .ndm_state = nbma ? NUD_REACHABLE : NUD_FAILED, - }; - znl_rta_push(zb, NDA_DST, sockunion_get_addr(proto), - family2addrsize(sockunion_family(proto))); - if (nbma) - znl_rta_push(zb, NDA_LLADDR, sockunion_get_addr(nbma), - family2addrsize(sockunion_family(nbma))); - znl_nlmsg_complete(zb, n); - zbuf_send(zb, netlink_req_fd); - zbuf_recv(zb, netlink_req_fd); - zbuf_free(zb); + nhrp_send_zebra_nbr(proto, nbma, ifp); } static void netlink_log_register(int fd, int group) diff --git a/nhrpd/nhrp_route.c b/nhrpd/nhrp_route.c index 746b585ed..06a9564e8 100644 --- a/nhrpd/nhrp_route.c +++ b/nhrpd/nhrp_route.c @@ -392,6 +392,32 @@ static void nhrp_table_node_cleanup(struct route_table *table, XFREE(MTYPE_NHRP_ROUTE, node->info); } +void nhrp_send_zebra_nbr(union sockunion *in, + union sockunion *out, + struct interface *ifp) +{ + struct stream *s; + + if (!zclient || zclient->sock < 0) + return; + s = zclient->obuf; + stream_reset(s); + zclient_create_header(s, + out ? ZEBRA_NEIGH_ADD : ZEBRA_NEIGH_DEL, + ifp->vrf_id); + stream_putc(s, sockunion_family(in)); + stream_write(s, sockunion_get_addr(in), sockunion_get_addrlen(in)); + if (out) { + stream_putc(s, sockunion_family(out)); + stream_write(s, sockunion_get_addr(out), + sockunion_get_addrlen(out)); + } + stream_putl(s, ifp->ifindex); + + stream_putw_at(s, 0, stream_get_endp(s)); + zclient_send_message(zclient); +} + void nhrp_zebra_terminate(void) { nhrp_zebra_register_neigh(VRF_DEFAULT, AFI_IP, false); diff --git a/nhrpd/nhrpd.h b/nhrpd/nhrpd.h index 6e7ddda18..0f4635d3d 100644 --- a/nhrpd/nhrpd.h +++ b/nhrpd/nhrpd.h @@ -88,6 +88,9 @@ static inline int notifier_active(struct notifier_list *l) void nhrp_zebra_init(void); void nhrp_zebra_terminate(void); +void nhrp_send_zebra_nbr(union sockunion *in, + union sockunion *out, + struct interface *ifp); struct zbuf; struct nhrp_vc; 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, }; |