From 077c07cc58be1fbbe28a2df71cd884af87b121a7 Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Thu, 19 Dec 2019 18:33:56 +0100 Subject: [PATCH 01/11] zebra: storage of gre information in zebra layer zebra is able to get information about gre tunnels. zebra_gre file is created to handle hooks, but is not yet used. also, debug zebra gre command is done to add gre traces. A zebra_gre file is used for complementary actions that may be needed. Signed-off-by: Philippe Guibert --- include/linux/if_tunnel.h | 71 +++++++++++++++++++++++++++++++++++++++ zebra/debug.c | 2 +- zebra/if_netlink.c | 52 ++++++++++++++++++++++++++++ zebra/interface.c | 31 +++++++++++++++-- zebra/interface.h | 4 +++ zebra/zebra_l2.c | 26 ++++++++++++++ zebra/zebra_l2.h | 17 ++++++++++ 7 files changed, 200 insertions(+), 3 deletions(-) create mode 100644 include/linux/if_tunnel.h diff --git a/include/linux/if_tunnel.h b/include/linux/if_tunnel.h new file mode 100644 index 0000000000..982a1b60d0 --- /dev/null +++ b/include/linux/if_tunnel.h @@ -0,0 +1,71 @@ +#ifndef _IF_TUNNEL_H_ +#define _IF_TUNNEL_H_ + +#include +#include +#include +#include +#include + + +#define SIOCGETTUNNEL (SIOCDEVPRIVATE + 0) +#define SIOCADDTUNNEL (SIOCDEVPRIVATE + 1) +#define SIOCDELTUNNEL (SIOCDEVPRIVATE + 2) +#define SIOCCHGTUNNEL (SIOCDEVPRIVATE + 3) +#define SIOCGETPRL (SIOCDEVPRIVATE + 4) +#define SIOCADDPRL (SIOCDEVPRIVATE + 5) +#define SIOCDELPRL (SIOCDEVPRIVATE + 6) +#define SIOCCHGPRL (SIOCDEVPRIVATE + 7) + +#define GRE_CSUM __cpu_to_be16(0x8000) +#define GRE_ROUTING __cpu_to_be16(0x4000) +#define GRE_KEY __cpu_to_be16(0x2000) +#define GRE_SEQ __cpu_to_be16(0x1000) +#define GRE_STRICT __cpu_to_be16(0x0800) +#define GRE_REC __cpu_to_be16(0x0700) +#define GRE_FLAGS __cpu_to_be16(0x00F8) +#define GRE_VERSION __cpu_to_be16(0x0007) + +struct ip_tunnel_parm { + char name[IFNAMSIZ]; + int link; + __be16 i_flags; + __be16 o_flags; + __be32 i_key; + __be32 o_key; + struct iphdr iph; +}; + +/* SIT-mode i_flags */ +#define SIT_ISATAP 0x0001 + +struct ip_tunnel_prl { + __be32 addr; + __u16 flags; + __u16 __reserved; + __u32 datalen; + __u32 __reserved2; + /* data follows */ +}; + +/* PRL flags */ +#define PRL_DEFAULT 0x0001 + +enum { + IFLA_GRE_UNSPEC, + IFLA_GRE_LINK, + IFLA_GRE_IFLAGS, + IFLA_GRE_OFLAGS, + IFLA_GRE_IKEY, + IFLA_GRE_OKEY, + IFLA_GRE_LOCAL, + IFLA_GRE_REMOTE, + IFLA_GRE_TTL, + IFLA_GRE_TOS, + IFLA_GRE_PMTUDISC, + __IFLA_GRE_MAX, +}; + +#define IFLA_GRE_MAX (__IFLA_GRE_MAX - 1) + +#endif /* _IF_TUNNEL_H_ */ diff --git a/zebra/debug.c b/zebra/debug.c index a8ddf6ba64..88a3d98815 100644 --- a/zebra/debug.c +++ b/zebra/debug.c @@ -178,7 +178,7 @@ DEFPY (debug_zebra_mpls, return CMD_SUCCESS; } -DEFUN (debug_zebra_vxlan, +DEFPY (debug_zebra_vxlan, debug_zebra_vxlan_cmd, "debug zebra vxlan", DEBUG_STR diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index 6aaf9d94f3..bc74babd19 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -29,10 +29,13 @@ * Reference - https://sourceware.org/ml/libc-alpha/2013-01/msg00599.html */ #define _LINUX_IN6_H +#define _LINUX_IF_H +#define _LINUX_IP_H #include #include #include +#include #include #include #include @@ -289,6 +292,8 @@ static void netlink_determine_zebra_iftype(const char *kind, *zif_type = ZEBRA_IF_BOND; else if (strcmp(kind, "bond_slave") == 0) *zif_type = ZEBRA_IF_BOND_SLAVE; + else if (strcmp(kind, "gre") == 0) + *zif_type = ZEBRA_IF_GRE; } #define parse_rtattr_nested(tb, max, rta) \ @@ -492,6 +497,43 @@ static int netlink_extract_vlan_info(struct rtattr *link_data, return 0; } +static int netlink_extract_gre_info(struct rtattr *link_data, + struct zebra_l2info_gre *gre_info) +{ + struct rtattr *attr[IFLA_GRE_MAX + 1]; + + memset(gre_info, 0, sizeof(*gre_info)); + memset(attr, 0, sizeof(attr)); + parse_rtattr_nested(attr, IFLA_GRE_MAX, link_data); + + if (!attr[IFLA_GRE_LOCAL]) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "IFLA_GRE_LOCAL missing from GRE IF message"); + } else + gre_info->vtep_ip = + *(struct in_addr *)RTA_DATA(attr[IFLA_GRE_LOCAL]); + if (!attr[IFLA_GRE_REMOTE]) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "IFLA_GRE_REMOTE missing from GRE IF message"); + } else + gre_info->vtep_ip_remote = + *(struct in_addr *)RTA_DATA(attr[IFLA_GRE_REMOTE]); + + if (!attr[IFLA_GRE_LINK]) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("IFLA_GRE_LINK missing from GRE IF message"); + } else + gre_info->ifindex_link = + *(ifindex_t *)RTA_DATA(attr[IFLA_GRE_LINK]); + if (attr[IFLA_GRE_IKEY]) + gre_info->ikey = *(uint32_t *)RTA_DATA(attr[IFLA_GRE_IKEY]); + if (attr[IFLA_GRE_OKEY]) + gre_info->okey = *(uint32_t *)RTA_DATA(attr[IFLA_GRE_OKEY]); + return 0; +} + static int netlink_extract_vxlan_info(struct rtattr *link_data, struct zebra_l2info_vxlan *vxl_info) { @@ -572,6 +614,16 @@ static void netlink_interface_update_l2info(struct interface *ifp, vxlan_info.ifindex_link) zebra_if_update_link(ifp, vxlan_info.ifindex_link, link_nsid); + } else if (IS_ZEBRA_IF_GRE(ifp)) { + struct zebra_l2info_gre gre_info; + + netlink_extract_gre_info(link_data, &gre_info); + gre_info.link_nsid = link_nsid; + zebra_l2_greif_add_update(ifp, &gre_info, add); + if (link_nsid != NS_UNKNOWN && + gre_info.ifindex_link) + zebra_if_update_link(ifp, gre_info.ifindex_link, + link_nsid); } } diff --git a/zebra/interface.c b/zebra/interface.c index 4b708496a1..5f3ee9428c 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -1066,8 +1066,9 @@ void if_up(struct interface *ifp) zif->link_ifindex); if (link_if) zebra_vxlan_svi_up(ifp, link_if); - } else if (IS_ZEBRA_IF_MACVLAN(ifp)) + } else if (IS_ZEBRA_IF_MACVLAN(ifp)) { zebra_vxlan_macvlan_up(ifp); + } if (zif->es_info.es) zebra_evpn_es_if_oper_state_change(zif, true /*up*/); @@ -1105,8 +1106,9 @@ void if_down(struct interface *ifp) zif->link_ifindex); if (link_if) zebra_vxlan_svi_down(ifp, link_if); - } else if (IS_ZEBRA_IF_MACVLAN(ifp)) + } else if (IS_ZEBRA_IF_MACVLAN(ifp)) { zebra_vxlan_macvlan_down(ifp); + } if (zif->es_info.es) zebra_evpn_es_if_oper_state_change(zif, false /*up*/); @@ -1304,6 +1306,9 @@ static const char *zebra_ziftype_2str(zebra_iftype_t zif_type) case ZEBRA_IF_MACVLAN: return "macvlan"; + case ZEBRA_IF_GRE: + return "GRE"; + default: return "Unknown"; } @@ -1576,6 +1581,28 @@ static void if_dump_vty(struct vty *vty, struct interface *ifp) ifp->name); } vty_out(vty, "\n"); + } else if (IS_ZEBRA_IF_GRE(ifp)) { + struct zebra_l2info_gre *gre_info; + + gre_info = &zebra_if->l2info.gre; + if (gre_info->vtep_ip.s_addr != INADDR_ANY) { + vty_out(vty, " VTEP IP: %pI4", &gre_info->vtep_ip); + if (gre_info->vtep_ip_remote.s_addr != INADDR_ANY) + vty_out(vty, " , remote %pI4", + &gre_info->vtep_ip_remote); + vty_out(vty, "\n"); + } + if (gre_info->ifindex_link && + (gre_info->link_nsid != NS_UNKNOWN)) { + struct interface *ifp; + + ifp = if_lookup_by_index_per_ns( + zebra_ns_lookup(gre_info->link_nsid), + gre_info->ifindex_link); + vty_out(vty, " Link Interface %s\n", + ifp == NULL ? "Unknown" : + ifp->name); + } } if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp)) { diff --git a/zebra/interface.h b/zebra/interface.h index 67eb1176b9..753eb6b58f 100644 --- a/zebra/interface.h +++ b/zebra/interface.h @@ -263,6 +263,7 @@ typedef enum { ZEBRA_IF_VETH, /* VETH interface*/ ZEBRA_IF_BOND, /* Bond */ ZEBRA_IF_BOND_SLAVE, /* Bond */ + ZEBRA_IF_GRE, /* GRE interface */ } zebra_iftype_t; /* Zebra "slave" interface type */ @@ -442,6 +443,9 @@ DECLARE_HOOK(zebra_if_config_wr, (struct vty * vty, struct interface *ifp), #define IS_ZEBRA_IF_BOND(ifp) \ (((struct zebra_if *)(ifp->info))->zif_type == ZEBRA_IF_BOND) +#define IS_ZEBRA_IF_GRE(ifp) \ + (((struct zebra_if *)(ifp->info))->zif_type == ZEBRA_IF_GRE) + #define IS_ZEBRA_IF_BRIDGE_SLAVE(ifp) \ (((struct zebra_if *)(ifp->info))->zif_slave_type \ == ZEBRA_IF_SLAVE_BRIDGE) diff --git a/zebra/zebra_l2.c b/zebra/zebra_l2.c index c3fbff2723..71fac556e1 100644 --- a/zebra/zebra_l2.c +++ b/zebra/zebra_l2.c @@ -289,6 +289,32 @@ void zebra_l2_vlanif_update(struct interface *ifp, memcpy(&zif->l2info.vl, vlan_info, sizeof(*vlan_info)); } +/* + * Update L2 info for a GRE interface. This is called upon interface + * addition as well as update. Upon add/update, need to inform + * clients about GRE information. + */ +void zebra_l2_greif_add_update(struct interface *ifp, + struct zebra_l2info_gre *gre_info, int add) +{ + struct zebra_if *zif; + struct in_addr old_vtep_ip; + + zif = ifp->info; + assert(zif); + + if (add) { + memcpy(&zif->l2info.gre, gre_info, sizeof(*gre_info)); + return; + } + + old_vtep_ip = zif->l2info.gre.vtep_ip; + if (IPV4_ADDR_SAME(&old_vtep_ip, &gre_info->vtep_ip)) + return; + + zif->l2info.gre.vtep_ip = gre_info->vtep_ip; +} + /* * 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 diff --git a/zebra/zebra_l2.h b/zebra/zebra_l2.h index 1834430287..6572f344c4 100644 --- a/zebra/zebra_l2.h +++ b/zebra/zebra_l2.h @@ -54,6 +54,18 @@ struct zebra_l2info_vlan { vlanid_t vid; /* VLAN id */ }; +/* zebra L2 interface information - GRE interface */ +struct zebra_l2info_gre { + struct in_addr vtep_ip; /* IFLA_GRE_LOCAL */ + struct in_addr vtep_ip_remote; /* IFLA_GRE_REMOTE */ + uint32_t ikey; + uint32_t okey; + ifindex_t ifindex_link; /* Interface index of interface + * linked with GRE + */ + ns_id_t link_nsid; +}; + /* zebra L2 interface information - VXLAN interface */ struct zebra_l2info_vxlan { vni_t vni; /* VNI */ @@ -75,6 +87,7 @@ union zebra_l2if_info { struct zebra_l2info_bridge br; struct zebra_l2info_vlan vl; struct zebra_l2info_vxlan vxl; + struct zebra_l2info_gre gre; }; /* NOTE: These macros are to be invoked only in the "correct" context. @@ -96,11 +109,15 @@ extern void zebra_l2_bridge_add_update(struct interface *ifp, extern void zebra_l2_bridge_del(struct interface *ifp); extern void zebra_l2_vlanif_update(struct interface *ifp, struct zebra_l2info_vlan *vlan_info); +extern void zebra_l2_greif_add_update(struct interface *ifp, + struct zebra_l2info_gre *vxlan_info, + int add); extern void zebra_l2_vxlanif_add_update(struct interface *ifp, struct zebra_l2info_vxlan *vxlan_info, int add); extern void zebra_l2_vxlanif_update_access_vlan(struct interface *ifp, vlanid_t access_vlan); +extern void zebra_l2_greif_del(struct interface *ifp); extern void zebra_l2_vxlanif_del(struct interface *ifp); extern void zebra_l2if_update_bridge_slave(struct interface *ifp, ifindex_t bridge_ifindex, From 632d83067c034609c3507e5c0e3d53c71d9c7fc7 Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Fri, 20 Dec 2019 10:34:01 +0100 Subject: [PATCH 02/11] zebra: add 3 new gre commands, and enforce synchro mecanism 3 new gre commands are available: - GRE_GET to permit a daemon to retrieve gre information. - GRE_UPDATe is the reply message from zebra to the daemon. as it is a syncronous request, the GRE_GET expected will have to match the vrf id where the gre information is wished. this has an impact on label manager with change in APIs. - SET_GRE_SOURCE. this command will be stubbed for now, assuming that the gre interface is set accordingly by external script. Signed-off-by: Philippe Guibert --- lib/log.c | 5 ++++- lib/zclient.h | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/log.c b/lib/log.c index ca2f501686..0edf5b3e9b 100644 --- a/lib/log.c +++ b/lib/log.c @@ -472,7 +472,10 @@ static const struct zebra_desc_table command_types[] = { DESC_ENTRY(ZEBRA_NHRP_NEIGH_UNREGISTER), DESC_ENTRY(ZEBRA_NEIGH_IP_ADD), DESC_ENTRY(ZEBRA_NEIGH_IP_DEL), - DESC_ENTRY(ZEBRA_CONFIGURE_ARP)}; + DESC_ENTRY(ZEBRA_CONFIGURE_ARP), + DESC_ENTRY(ZEBRA_GRE_GET), + DESC_ENTRY(ZEBRA_GRE_UPDATE), + DESC_ENTRY(ZEBRA_GRE_SOURCE_SET)}; #undef DESC_ENTRY static const struct zebra_desc_table unknown = {0, "unknown", '?'}; diff --git a/lib/zclient.h b/lib/zclient.h index e8fff4b881..f9e1bdc370 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -232,6 +232,9 @@ typedef enum { ZEBRA_NEIGH_IP_ADD, ZEBRA_NEIGH_IP_DEL, ZEBRA_CONFIGURE_ARP, + ZEBRA_GRE_GET, + ZEBRA_GRE_UPDATE, + ZEBRA_GRE_SOURCE_SET, } zebra_message_types_t; enum zebra_error_types { From b716ab61e2a40da54115a39297e3aca0834bbea7 Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Fri, 20 Dec 2019 10:51:25 +0100 Subject: [PATCH 03/11] zebra: add stub implementation for zebra gre source set this functionality is stubbed. Signed-off-by: Philippe Guibert --- zebra/rt_netlink.c | 8 ++++++++ zebra/zapi_msg.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index d2ec7da57c..d8405f277e 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -3890,6 +3890,14 @@ netlink_put_neigh_update_msg(struct nl_batch *bth, struct zebra_dplane_ctx *ctx) false); } +int kernel_configure_if_link(struct interface *ifp, + struct interface *link_ifp, + ns_id_t ns_id) +{ + /* TODO */ + return 0; +} + /* * MPLS label forwarding table change via netlink interface, using dataplane * context information. diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 77a9188fe8..645cb2bd0c 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -3373,6 +3373,34 @@ stream_failure: return; } +static inline void zebra_gre_source_set(ZAPI_HANDLER_ARGS) +{ + struct stream *s; + ifindex_t idx, link_idx; + vrf_id_t link_vrf_id; + struct interface *ifp; + struct interface *ifp_link; + ns_id_t ns_id; + vrf_id_t vrf_id = zvrf->vrf->vrf_id; + + s = msg; + STREAM_GETL(s, idx); + ifp = if_lookup_by_index(idx, vrf_id); + STREAM_GETL(s, link_idx); + STREAM_GETL(s, link_vrf_id); + ifp_link = if_lookup_by_index(link_idx, link_vrf_id); + if (!ifp_link || !ifp) { + zlog_warn("GRE (index %u, VRF %u) or GRE link interface (index %u, VRF %u) not found, when setting GRE params", + idx, vrf_id, link_idx, link_vrf_id); + return; + } + ns_id = zvrf->zns->ns_id; + kernel_configure_if_link(ifp, ifp_link, ns_id); + + stream_failure: + return; +} + static void zsend_error_msg(struct zserv *client, enum zebra_error_types error, struct zmsghdr *bad_hdr) { @@ -3488,6 +3516,7 @@ void (*const zserv_handlers[])(ZAPI_HANDLER_ARGS) = { [ZEBRA_NHRP_NEIGH_REGISTER] = zebra_neigh_register, [ZEBRA_NHRP_NEIGH_UNREGISTER] = zebra_neigh_unregister, [ZEBRA_CONFIGURE_ARP] = zebra_configure_arp, + [ZEBRA_GRE_SOURCE_SET] = zebra_gre_source_set, }; /* From d17af8dd0409f1622b055102146b2887d411ec6c Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Fri, 20 Dec 2019 11:06:05 +0100 Subject: [PATCH 04/11] lib, zebra: get gre information the get gre information code is obtained by nhrp, via zebra. Signed-off-by: Philippe Guibert --- lib/zclient.c | 30 ++++++++++++++++++++++++++ lib/zclient.h | 3 +++ zebra/zapi_msg.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+) diff --git a/lib/zclient.c b/lib/zclient.c index b1aea55afa..e2f99aebf3 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -3931,6 +3931,11 @@ static int zclient_read(struct thread *thread) (*zclient->neighbor_get)(command, zclient, length, vrf_id); break; + case ZEBRA_GRE_UPDATE: + if (zclient->gre_update) + (*zclient->gre_update)(command, zclient, + length, vrf_id); + break; default: break; } @@ -4252,3 +4257,28 @@ int zclient_neigh_ip_decode(struct stream *s, struct zapi_neigh_ip *api) stream_failure: return -1; } + +int zclient_send_zebra_gre_request(struct zclient *client, + struct interface *ifp) +{ + struct stream *s; + ifindex_t idx_local; + int ret; + + if (!client || client->sock < 0) { + zlog_err("%s : zclient not ready", __func__); + return -1; + } + s = client->obuf; + stream_reset(s); + zclient_create_header(s, + ZEBRA_GRE_GET, + ifp->vrf_id); + stream_putl(s, ifp->ifindex); + stream_putw_at(s, 0, stream_get_endp(s)); + zclient_send_message(client); + return 0; +stream_failure: + zlog_err("%s(): error reading response ..", __func__); + return 0; +} diff --git a/lib/zclient.h b/lib/zclient.h index f9e1bdc370..8c27916542 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -396,6 +396,7 @@ struct zclient { void (*neighbor_added)(ZAPI_CALLBACK_ARGS); void (*neighbor_removed)(ZAPI_CALLBACK_ARGS); void (*neighbor_get)(ZAPI_CALLBACK_ARGS); + void (*gre_update)(ZAPI_CALLBACK_ARGS); }; /* Zebra API message flag. */ @@ -1231,6 +1232,8 @@ struct zapi_client_close_info { extern int zapi_client_close_notify_decode(struct stream *s, struct zapi_client_close_info *info); +extern int zclient_send_zebra_gre_request(struct zclient *client, + struct interface *ifp); #ifdef __cplusplus } #endif diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 645cb2bd0c..d36c6becd7 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -3240,6 +3240,61 @@ stream_failure: return; } +static inline void zebra_gre_get(ZAPI_HANDLER_ARGS) +{ + struct stream *s; + ifindex_t idx; + struct interface *ifp; + struct zebra_if *zebra_if = NULL; + struct zebra_l2info_gre *gre_info; + struct interface *ifp_link = NULL; + vrf_id_t vrf_id_link = VRF_UNKNOWN; + vrf_id_t vrf_id = zvrf->vrf->vrf_id; + + s = msg; + STREAM_GETL(s, idx); + ifp = if_lookup_by_index(idx, vrf_id); + + if (ifp) + zebra_if = ifp->info; + + s = stream_new(ZEBRA_MAX_PACKET_SIZ); + + zclient_create_header(s, ZEBRA_GRE_UPDATE, vrf_id); + + if (ifp && IS_ZEBRA_IF_GRE(ifp) && zebra_if) { + gre_info = &zebra_if->l2info.gre; + + stream_putl(s, idx); + stream_putl(s, gre_info->ikey); + stream_putl(s, gre_info->ikey); + stream_putl(s, gre_info->ifindex_link); + + ifp_link = if_lookup_by_index_per_ns( + zebra_ns_lookup(gre_info->link_nsid), + gre_info->ifindex_link); + if (ifp_link) + vrf_id_link = ifp_link->vrf_id; + stream_putl(s, vrf_id_link); + stream_putl(s, gre_info->vtep_ip.s_addr); + stream_putl(s, gre_info->vtep_ip_remote.s_addr); + } else { + stream_putl(s, idx); + stream_putl(s, 0); + stream_putl(s, 0); + stream_putl(s, IFINDEX_INTERNAL); + stream_putl(s, VRF_UNKNOWN); + stream_putl(s, 0); + } + /* Write packet size. */ + stream_putw_at(s, 0, stream_get_endp(s)); + zserv_send_message(client, s); + + return; + stream_failure: + return; +} + static inline void zebra_configure_arp(ZAPI_HANDLER_ARGS) { struct stream *s; @@ -3516,6 +3571,7 @@ void (*const zserv_handlers[])(ZAPI_HANDLER_ARGS) = { [ZEBRA_NHRP_NEIGH_REGISTER] = zebra_neigh_register, [ZEBRA_NHRP_NEIGH_UNREGISTER] = zebra_neigh_unregister, [ZEBRA_CONFIGURE_ARP] = zebra_configure_arp, + [ZEBRA_GRE_GET] = zebra_gre_get, [ZEBRA_GRE_SOURCE_SET] = zebra_gre_source_set, }; From 7f48cfa5e4d93bb8899e0eb815074741df3c8177 Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Fri, 20 Dec 2019 11:10:34 +0100 Subject: [PATCH 05/11] nhrpd: redirect netlink gre with zebra as zebra has a new api to get gre and set gre source commands, netlink gre get and netlink gre source function calls are redirected to zebra by using the zapi interface. Signed-off-by: Philippe Guibert --- nhrpd/nhrp_interface.c | 92 +++++++++++++++++++++++++++++++++--------- nhrpd/nhrp_route.c | 77 +++++++++++++++++++++++++++++++++++ nhrpd/nhrpd.h | 33 +++++++++++++-- 3 files changed, 180 insertions(+), 22 deletions(-) diff --git a/nhrpd/nhrp_interface.c b/nhrpd/nhrp_interface.c index 402ffe9a24..12c86c3876 100644 --- a/nhrpd/nhrp_interface.c +++ b/nhrpd/nhrp_interface.c @@ -20,8 +20,47 @@ #include "nhrpd.h" #include "os.h" #include "netlink.h" +#include "hash.h" DEFINE_MTYPE_STATIC(NHRPD, NHRP_IF, "NHRP interface"); +DEFINE_MTYPE_STATIC(NHRPD, NHRP_IF_GRE, "NHRP GRE interface"); + +struct hash *nhrp_gre_list; + +static unsigned int nhrp_gre_info_key(const void *data) +{ + const struct nhrp_gre_info *r = data; + + return r->ifindex; +} + +static bool nhrp_gre_info_cmp(const void *data, const void *key) +{ + const struct nhrp_gre_info *a = data, *b = key; + + if (a->ifindex == b->ifindex) + return true; + return false; +} + +static void *nhrp_interface_gre_alloc(void *data) +{ + struct nhrp_gre_info *a; + struct nhrp_gre_info *b = data; + + a = XMALLOC(MTYPE_NHRP_IF_GRE, sizeof(struct nhrp_gre_info)); + memcpy(a, b, sizeof(struct nhrp_gre_info)); + return a; +} + +struct nhrp_gre_info *nhrp_gre_info_alloc(struct nhrp_gre_info *p) +{ + struct nhrp_gre_info *a; + + a = (struct nhrp_gre_info *)hash_get(nhrp_gre_list, p, + nhrp_interface_gre_alloc); + return a; +} static void nhrp_interface_update_cache_config(struct interface *ifp, bool available, @@ -74,6 +113,9 @@ void nhrp_interface_init(void) { hook_register_prio(if_add, 0, nhrp_if_new_hook); hook_register_prio(if_del, 0, nhrp_if_delete_hook); + + nhrp_gre_list = hash_create(nhrp_gre_info_key, nhrp_gre_info_cmp, + "NHRP GRE list Hash"); } void nhrp_interface_update_mtu(struct interface *ifp, afi_t afi) @@ -102,14 +144,16 @@ static void nhrp_interface_update_source(struct interface *ifp) { struct nhrp_interface *nifp = ifp->info; - if (!nifp->source || !nifp->nbmaifp - || (ifindex_t)nifp->linkidx == nifp->nbmaifp->ifindex) + if (!nifp->source || !nifp->nbmaifp || + ((ifindex_t)nifp->link_idx == nifp->nbmaifp->ifindex && + (nifp->link_vrf_id == nifp->nbmaifp->vrf_id))) return; - nifp->linkidx = nifp->nbmaifp->ifindex; - debugf(NHRP_DEBUG_IF, "%s: bound device index changed to %d", ifp->name, - nifp->linkidx); - netlink_gre_set_link(ifp->ifindex, nifp->linkidx); + nifp->link_idx = nifp->nbmaifp->ifindex; + nifp->link_vrf_id = nifp->nbmaifp->vrf_id; + debugf(NHRP_DEBUG_IF, "%s: bound device index changed to %d, vr %u", + ifp->name, nifp->link_idx, nifp->link_vrf_id); + nhrp_send_zebra_gre_source_set(ifp, nifp->link_idx, nifp->link_vrf_id); } static void nhrp_interface_interface_notifier(struct notifier_block *n, @@ -136,7 +180,8 @@ static void nhrp_interface_interface_notifier(struct notifier_block *n, } } -static void nhrp_interface_update_nbma(struct interface *ifp) +void nhrp_interface_update_nbma(struct interface *ifp, + struct nhrp_gre_info *gre_info) { struct nhrp_interface *nifp = ifp->info, *nbmanifp = NULL; struct interface *nbmaifp = NULL; @@ -145,21 +190,32 @@ static void nhrp_interface_update_nbma(struct interface *ifp) sockunion_family(&nbma) = AF_UNSPEC; if (nifp->source) - nbmaifp = if_lookup_by_name(nifp->source, VRF_DEFAULT); + nbmaifp = if_lookup_by_name(nifp->source, nifp->link_vrf_id); switch (ifp->ll_type) { case ZEBRA_LLT_IPGRE: { struct in_addr saddr = {0}; - netlink_gre_get_info(ifp->ifindex, &nifp->grekey, - &nifp->linkidx, &saddr); + + if (!gre_info) { + nhrp_send_zebra_gre_request(ifp); + return; + } + nifp->i_grekey = gre_info->ikey; + nifp->o_grekey = gre_info->okey; + nifp->link_idx = gre_info->ifindex_link; + nifp->link_vrf_id = gre_info->vrfid_link; + saddr.s_addr = gre_info->vtep_ip.s_addr; + debugf(NHRP_DEBUG_IF, "%s: GRE: %x %x %x", ifp->name, - nifp->grekey, nifp->linkidx, saddr.s_addr); - if (saddr.s_addr != INADDR_ANY) - sockunion_set(&nbma, AF_INET, (uint8_t *)&saddr.s_addr, + nifp->i_grekey, nifp->link_idx, saddr.s_addr); + if (saddr.s_addr) + sockunion_set(&nbma, AF_INET, + (uint8_t *)&saddr.s_addr, sizeof(saddr.s_addr)); - else if (!nbmaifp && nifp->linkidx != IFINDEX_INTERNAL) + else if (!nbmaifp && nifp->link_idx != IFINDEX_INTERNAL) nbmaifp = - if_lookup_by_index(nifp->linkidx, VRF_DEFAULT); + if_lookup_by_index(nifp->link_idx, + nifp->link_vrf_id); } break; default: break; @@ -322,7 +378,7 @@ int nhrp_ifp_create(struct interface *ifp) ifp->name, ifp->ifindex, ifp->ll_type, if_link_type_str(ifp->ll_type)); - nhrp_interface_update_nbma(ifp); + nhrp_interface_update_nbma(ifp, NULL); return 0; } @@ -402,7 +458,7 @@ static void nhrp_interface_update_cache_config(struct interface *ifp, bool avail int nhrp_ifp_up(struct interface *ifp) { debugf(NHRP_DEBUG_IF, "if-up: %s", ifp->name); - nhrp_interface_update_nbma(ifp); + nhrp_interface_update_nbma(ifp, NULL); return 0; } @@ -493,5 +549,5 @@ void nhrp_interface_set_source(struct interface *ifp, const char *ifname) free(nifp->source); nifp->source = ifname ? strdup(ifname) : NULL; - nhrp_interface_update_nbma(ifp); + nhrp_interface_update_nbma(ifp, NULL); } diff --git a/nhrpd/nhrp_route.c b/nhrpd/nhrp_route.c index 23fa0771ef..1f513b7c0e 100644 --- a/nhrpd/nhrp_route.c +++ b/nhrpd/nhrp_route.c @@ -380,6 +380,7 @@ void nhrp_zebra_init(void) zclient->neighbor_added = nhrp_neighbor_operation; zclient->neighbor_removed = nhrp_neighbor_operation; zclient->neighbor_get = nhrp_neighbor_operation; + zclient->gre_update = nhrp_gre_update; zclient_init(zclient, ZEBRA_ROUTE_NHRP, 0, &nhrpd_privs); } @@ -412,6 +413,32 @@ void nhrp_send_zebra_configure_arp(struct interface *ifp, int family) zclient_send_message(zclient); } +void nhrp_send_zebra_gre_source_set(struct interface *ifp, + unsigned int link_idx, + vrf_id_t link_vrf_id) +{ + struct stream *s; + + if (!zclient || zclient->sock < 0) { + zlog_err("%s : zclient not ready", __func__); + return; + } + if (link_idx == IFINDEX_INTERNAL || link_vrf_id == VRF_UNKNOWN) { + /* silently ignore */ + return; + } + s = zclient->obuf; + stream_reset(s); + zclient_create_header(s, + ZEBRA_GRE_SOURCE_SET, + ifp->vrf_id); + stream_putl(s, ifp->ifindex); + stream_putl(s, link_idx); + stream_putl(s, link_vrf_id); + stream_putw_at(s, 0, stream_get_endp(s)); + zclient_send_message(zclient); +} + void nhrp_send_zebra_nbr(union sockunion *in, union sockunion *out, struct interface *ifp) @@ -429,6 +456,11 @@ void nhrp_send_zebra_nbr(union sockunion *in, zclient_send_message(zclient); } +int nhrp_send_zebra_gre_request(struct interface *ifp) +{ + return zclient_send_zebra_gre_request(zclient, ifp); +} + void nhrp_zebra_terminate(void) { nhrp_zebra_register_neigh(VRF_DEFAULT, AFI_IP, false); @@ -441,3 +473,48 @@ void nhrp_zebra_terminate(void) route_table_finish(zebra_rib[AFI_IP]); route_table_finish(zebra_rib[AFI_IP6]); } + +void nhrp_gre_update(ZAPI_CALLBACK_ARGS) +{ + struct stream *s; + struct nhrp_gre_info gre_info, *val; + struct interface *ifp; + + /* result */ + s = zclient->ibuf; + if (vrf_id != VRF_DEFAULT) + return; + + /* read GRE information */ + STREAM_GETL(s, gre_info.ifindex); + STREAM_GETL(s, gre_info.ikey); + STREAM_GETL(s, gre_info.okey); + STREAM_GETL(s, gre_info.ifindex_link); + STREAM_GETL(s, gre_info.vrfid_link); + STREAM_GETL(s, gre_info.vtep_ip.s_addr); + STREAM_GETL(s, gre_info.vtep_ip_remote.s_addr); + if (gre_info.ifindex == IFINDEX_INTERNAL) + val = NULL; + else + val = hash_lookup(nhrp_gre_list, &gre_info); + if (val) { + if (gre_info.vtep_ip.s_addr != val->vtep_ip.s_addr || + gre_info.vrfid_link != val->vrfid_link || + gre_info.ifindex_link != val->ifindex_link || + gre_info.ikey != val->ikey || + gre_info.okey != val->okey) { + /* update */ + memcpy(val, &gre_info, sizeof(struct nhrp_gre_info)); + } + } else { + val = nhrp_gre_info_alloc(&gre_info); + } + ifp = if_lookup_by_index(gre_info.ifindex, vrf_id); + debugf(NHRP_DEBUG_EVENT, "%s: gre interface %d vr %d obtained from system", + ifp ? ifp->name : "", gre_info.ifindex, vrf_id); + if (ifp) + nhrp_interface_update_nbma(ifp, val); + return; +stream_failure: + zlog_err("%s(): error reading response ..", __func__); +} diff --git a/nhrpd/nhrpd.h b/nhrpd/nhrpd.h index 730f9b7d13..17abb04762 100644 --- a/nhrpd/nhrpd.h +++ b/nhrpd/nhrpd.h @@ -86,14 +86,22 @@ static inline int notifier_active(struct notifier_list *l) return !list_empty(&l->notifier_head); } +extern struct hash *nhrp_gre_list; + void nhrp_zebra_init(void); void nhrp_zebra_terminate(void); void nhrp_send_zebra_configure_arp(struct interface *ifp, int family); void nhrp_send_zebra_nbr(union sockunion *in, union sockunion *out, struct interface *ifp); -void nhrp_send_zebra_configure_arp(struct interface *ifp, - int family); + +void nhrp_send_zebra_gre_source_set(struct interface *ifp, + unsigned int link_idx, + vrf_id_t link_vrf_id); + +extern int nhrp_send_zebra_gre_request(struct interface *ifp); +extern struct nhrp_gre_info *nhrp_gre_info_alloc(struct nhrp_gre_info *p); + struct zbuf; struct nhrp_vc; struct nhrp_cache; @@ -300,8 +308,10 @@ struct nhrp_interface { char *ipsec_profile, *ipsec_fallback_profile, *source; union sockunion nbma; union sockunion nat_nbma; - unsigned int linkidx; - uint32_t grekey; + unsigned int link_idx; + unsigned int link_vrf_id; + uint32_t i_grekey; + uint32_t o_grekey; struct hash *peer_hash; struct hash *cache_config_hash; @@ -325,6 +335,18 @@ struct nhrp_interface { } afi[AFI_MAX]; }; +struct nhrp_gre_info { + ifindex_t ifindex; + struct in_addr vtep_ip; /* IFLA_GRE_LOCAL */ + struct in_addr vtep_ip_remote; /* IFLA_GRE_REMOTE */ + uint32_t ikey; + uint32_t okey; + ifindex_t ifindex_link; /* Interface index of interface + * linked with GRE + */ + vrf_id_t vrfid_link; +}; + extern struct zebra_privs_t nhrpd_privs; int sock_open_unix(const char *path); @@ -332,6 +354,8 @@ int sock_open_unix(const char *path); void nhrp_interface_init(void); void nhrp_interface_update(struct interface *ifp); void nhrp_interface_update_mtu(struct interface *ifp, afi_t afi); +void nhrp_interface_update_nbma(struct interface *ifp, + struct nhrp_gre_info *gre_info); int nhrp_interface_add(ZAPI_CALLBACK_ARGS); int nhrp_interface_delete(ZAPI_CALLBACK_ARGS); @@ -340,6 +364,7 @@ int nhrp_interface_down(ZAPI_CALLBACK_ARGS); int nhrp_interface_address_add(ZAPI_CALLBACK_ARGS); int nhrp_interface_address_delete(ZAPI_CALLBACK_ARGS); void nhrp_neighbor_operation(ZAPI_CALLBACK_ARGS); +void nhrp_gre_update(ZAPI_CALLBACK_ARGS); void nhrp_interface_notify_add(struct interface *ifp, struct notifier_block *n, notifier_fn_t fn); From aea6c49e01afccb68a6559832dd74924e13b8e61 Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Fri, 20 Dec 2019 11:23:05 +0100 Subject: [PATCH 06/11] nhrpd: cleaning netlink gre information flush netlink related dependencies with gre information. Add some linux headers required to compile with it. Signed-off-by: Philippe Guibert --- include/linux/if_packet.h | 16 ++++ lib/zclient.c | 5 -- nhrpd/linux.c | 6 +- nhrpd/netlink.h | 11 +-- nhrpd/netlink_arp.c | 8 -- nhrpd/netlink_gre.c | 152 -------------------------------------- nhrpd/nhrp_interface.c | 1 - nhrpd/nhrp_main.c | 2 - nhrpd/subdir.am | 1 - 9 files changed, 20 insertions(+), 182 deletions(-) create mode 100644 include/linux/if_packet.h delete mode 100644 nhrpd/netlink_gre.c diff --git a/include/linux/if_packet.h b/include/linux/if_packet.h new file mode 100644 index 0000000000..057edb33dc --- /dev/null +++ b/include/linux/if_packet.h @@ -0,0 +1,16 @@ +#ifndef __LINUX_IF_PACKET_H +#define __LINUX_IF_PACKET_H + +#include + +struct sockaddr_ll { + unsigned short sll_family; + __be16 sll_protocol; + int sll_ifindex; + unsigned short sll_hatype; + unsigned char sll_pkttype; + unsigned char sll_halen; + unsigned char sll_addr[8]; +}; + +#endif diff --git a/lib/zclient.c b/lib/zclient.c index e2f99aebf3..3ea1789441 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -4262,8 +4262,6 @@ int zclient_send_zebra_gre_request(struct zclient *client, struct interface *ifp) { struct stream *s; - ifindex_t idx_local; - int ret; if (!client || client->sock < 0) { zlog_err("%s : zclient not ready", __func__); @@ -4278,7 +4276,4 @@ int zclient_send_zebra_gre_request(struct zclient *client, stream_putw_at(s, 0, stream_get_endp(s)); zclient_send_message(client); return 0; -stream_failure: - zlog_err("%s(): error reading response ..", __func__); - return 0; } diff --git a/nhrpd/linux.c b/nhrpd/linux.c index f697311d49..b55e656562 100644 --- a/nhrpd/linux.c +++ b/nhrpd/linux.c @@ -21,16 +21,12 @@ #include #include #include -#include -#include -#include +#include #include -#include #include #include "nhrp_protocol.h" #include "os.h" -#include "netlink.h" #ifndef HAVE_STRLCPY size_t strlcpy(char *__restrict dest, diff --git a/nhrpd/netlink.h b/nhrpd/netlink.h index 5e971cabf1..f1143a2b5e 100644 --- a/nhrpd/netlink.h +++ b/nhrpd/netlink.h @@ -7,21 +7,16 @@ * (at your option) any later version. */ -#include +#include +#include +#include -union sockunion; -struct interface; extern int netlink_nflog_group; extern int netlink_mcast_nflog_group; -extern int netlink_req_fd; -void netlink_init(void); int netlink_configure_arp(unsigned int ifindex, int pf); void netlink_update_binding(struct interface *ifp, union sockunion *proto, union sockunion *nbma); void netlink_set_nflog_group(int nlgroup); -void netlink_gre_get_info(unsigned int ifindex, uint32_t *gre_key, - unsigned int *link_index, struct in_addr *saddr); -void netlink_gre_set_link(unsigned int ifindex, unsigned int link_index); diff --git a/nhrpd/netlink_arp.c b/nhrpd/netlink_arp.c index ecea0a9ec5..5fcb311888 100644 --- a/nhrpd/netlink_arp.c +++ b/nhrpd/netlink_arp.c @@ -25,7 +25,6 @@ #include "netlink.h" #include "znl.h" -int netlink_req_fd = -1; int netlink_nflog_group; static int netlink_log_fd = -1; static struct thread *netlink_log_thread; @@ -203,10 +202,3 @@ void nhrp_neighbor_operation(ZAPI_CALLBACK_ARGS) nhrp_cache_set_used(c, state == ZEBRA_NEIGH_STATE_REACHABLE); } } - -void netlink_init(void) -{ - netlink_req_fd = znl_open(NETLINK_ROUTE, 0); - if (netlink_req_fd < 0) - return; -} diff --git a/nhrpd/netlink_gre.c b/nhrpd/netlink_gre.c deleted file mode 100644 index 3fdfa9c313..0000000000 --- a/nhrpd/netlink_gre.c +++ /dev/null @@ -1,152 +0,0 @@ -/* NHRP netlink/GRE tunnel configuration code - * Copyright (c) 2014-2016 Timo Teräs - * - * This file is free software: you may copy, redistribute and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "debug.h" -#include "netlink.h" -#include "znl.h" - -static int __netlink_gre_get_data(struct zbuf *zb, struct zbuf *data, - int ifindex) -{ - struct nlmsghdr *n; - struct ifinfomsg *ifi; - struct zbuf payload, rtapayload; - struct rtattr *rta; - - debugf(NHRP_DEBUG_KERNEL, "netlink-link-gre: get-info %u", ifindex); - - n = znl_nlmsg_push(zb, RTM_GETLINK, NLM_F_REQUEST); - ifi = znl_push(zb, sizeof(*ifi)); - *ifi = (struct ifinfomsg){ - .ifi_index = ifindex, - }; - znl_nlmsg_complete(zb, n); - - if (zbuf_send(zb, netlink_req_fd) < 0 - || zbuf_recv(zb, netlink_req_fd) < 0) - return -1; - - n = znl_nlmsg_pull(zb, &payload); - if (!n) - return -1; - - if (n->nlmsg_type != RTM_NEWLINK) - return -1; - - ifi = znl_pull(&payload, sizeof(struct ifinfomsg)); - if (!ifi) - return -1; - - debugf(NHRP_DEBUG_KERNEL, - "netlink-link-gre: ifindex %u, receive msg_type %u, msg_flags %u", - ifi->ifi_index, n->nlmsg_type, n->nlmsg_flags); - - if (ifi->ifi_index != ifindex) - return -1; - - while ((rta = znl_rta_pull(&payload, &rtapayload)) != NULL) - if (rta->rta_type == IFLA_LINKINFO) - break; - if (!rta) - return -1; - - payload = rtapayload; - while ((rta = znl_rta_pull(&payload, &rtapayload)) != NULL) - if (rta->rta_type == IFLA_INFO_DATA) - break; - if (!rta) - return -1; - - *data = rtapayload; - return 0; -} - -void netlink_gre_get_info(unsigned int ifindex, uint32_t *gre_key, - unsigned int *link_index, struct in_addr *saddr) -{ - struct zbuf *zb = zbuf_alloc(8192), data, rtapl; - struct rtattr *rta; - - *link_index = 0; - *gre_key = 0; - saddr->s_addr = 0; - - if (__netlink_gre_get_data(zb, &data, ifindex) < 0) - goto err; - - while ((rta = znl_rta_pull(&data, &rtapl)) != NULL) { - switch (rta->rta_type) { - case IFLA_GRE_LINK: - *link_index = zbuf_get32(&rtapl); - break; - case IFLA_GRE_IKEY: - case IFLA_GRE_OKEY: - *gre_key = zbuf_get32(&rtapl); - break; - case IFLA_GRE_LOCAL: - saddr->s_addr = zbuf_get32(&rtapl); - break; - } - } -err: - zbuf_free(zb); -} - -void netlink_gre_set_link(unsigned int ifindex, unsigned int link_index) -{ - struct nlmsghdr *n; - struct ifinfomsg *ifi; - struct rtattr *rta_info, *rta_data, *rta; - struct zbuf *zr = zbuf_alloc(8192), data, rtapl; - struct zbuf *zb = zbuf_alloc(8192); - size_t len; - - if (__netlink_gre_get_data(zr, &data, ifindex) < 0) - goto err; - - n = znl_nlmsg_push(zb, RTM_NEWLINK, NLM_F_REQUEST); - ifi = znl_push(zb, sizeof(*ifi)); - *ifi = (struct ifinfomsg){ - .ifi_index = ifindex, - }; - rta_info = znl_rta_nested_push(zb, IFLA_LINKINFO); - znl_rta_push(zb, IFLA_INFO_KIND, "gre", 3); - rta_data = znl_rta_nested_push(zb, IFLA_INFO_DATA); - - znl_rta_push_u32(zb, IFLA_GRE_LINK, link_index); - while ((rta = znl_rta_pull(&data, &rtapl)) != NULL) { - if (rta->rta_type == IFLA_GRE_LINK) - continue; - len = zbuf_used(&rtapl); - znl_rta_push(zb, rta->rta_type, zbuf_pulln(&rtapl, len), len); - } - - znl_rta_nested_complete(zb, rta_data); - znl_rta_nested_complete(zb, rta_info); - - znl_nlmsg_complete(zb, n); - zbuf_send(zb, netlink_req_fd); - zbuf_recv(zb, netlink_req_fd); -err: - zbuf_free(zb); - zbuf_free(zr); -} diff --git a/nhrpd/nhrp_interface.c b/nhrpd/nhrp_interface.c index 12c86c3876..541e5a992a 100644 --- a/nhrpd/nhrp_interface.c +++ b/nhrpd/nhrp_interface.c @@ -19,7 +19,6 @@ #include "nhrpd.h" #include "os.h" -#include "netlink.h" #include "hash.h" DEFINE_MTYPE_STATIC(NHRPD, NHRP_IF, "NHRP interface"); diff --git a/nhrpd/nhrp_main.c b/nhrpd/nhrp_main.c index e9bce3e09a..c2111a7706 100644 --- a/nhrpd/nhrp_main.c +++ b/nhrpd/nhrp_main.c @@ -26,7 +26,6 @@ #include "filter.h" #include "nhrpd.h" -#include "netlink.h" #include "nhrp_errors.h" DEFINE_MGROUP(NHRPD, "NHRP"); @@ -154,7 +153,6 @@ int main(int argc, char **argv) assert(nhrpd_privs.change); nhrpd_privs.change(ZPRIVS_RAISE); - netlink_init(); evmgr_init(); nhrp_vc_init(); nhrp_packet_init(); diff --git a/nhrpd/subdir.am b/nhrpd/subdir.am index d00aecc1ea..9a186d6ed8 100644 --- a/nhrpd/subdir.am +++ b/nhrpd/subdir.am @@ -13,7 +13,6 @@ nhrpd_nhrpd_LDADD = lib/libfrr.la lib/libfrrcares.la $(LIBCAP) nhrpd_nhrpd_SOURCES = \ nhrpd/linux.c \ nhrpd/netlink_arp.c \ - nhrpd/netlink_gre.c \ nhrpd/nhrp_cache.c \ nhrpd/nhrp_errors.c \ nhrpd/nhrp_event.c \ From 372b887859b7e5739137b02a1cecf2ea702ba586 Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Thu, 11 Mar 2021 13:59:57 +0100 Subject: [PATCH 07/11] nhrpd: clean up SA warning with strncpy strncpy is replaced by strlcpy. Signed-off-by: Philippe Guibert --- nhrpd/linux.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/nhrpd/linux.c b/nhrpd/linux.c index b55e656562..4986bfb99c 100644 --- a/nhrpd/linux.c +++ b/nhrpd/linux.c @@ -7,23 +7,9 @@ * (at your option) any later version. */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include -#include #include -#include -#include -#include -#include -#include +#include "zebra.h" #include -#include -#include #include "nhrp_protocol.h" #include "os.h" From 62b4b7e44ae72cbd611a78cd7abe8558366af21c Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Thu, 11 Mar 2021 15:33:41 +0100 Subject: [PATCH 08/11] zebra: new dplane action to set gre link interface This action is initiated by nhrp and has been stubbed when moving to zebra. Now, a netlink request is forged to set the link interface of a gre interface if that gre interface does not have already a link interface. Signed-off-by: Philippe Guibert --- zebra/if_netlink.c | 60 +++++++++++++++++++++++- zebra/if_netlink.h | 3 ++ zebra/kernel_netlink.c | 3 ++ zebra/rt.h | 3 -- zebra/rt_netlink.c | 8 ---- zebra/rt_socket.c | 6 --- zebra/zapi_msg.c | 24 ++++++++-- zebra/zebra_dplane.c | 103 +++++++++++++++++++++++++++++++++++++++++ zebra/zebra_dplane.h | 11 +++++ zebra/zebra_errors.h | 1 + zebra/zebra_nhg.c | 1 + zebra/zebra_rib.c | 1 + 12 files changed, 203 insertions(+), 21 deletions(-) diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index bc74babd19..44ee8d9469 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -463,6 +463,46 @@ uint32_t kernel_get_speed(struct interface *ifp, int *error) return get_iflink_speed(ifp, error); } +static ssize_t +netlink_gre_set_msg_encoder(struct zebra_dplane_ctx *ctx, void *buf, + size_t buflen) +{ + struct { + struct nlmsghdr n; + struct ifinfomsg ifi; + char buf[]; + } *req = buf; + uint32_t link_idx; + struct rtattr *rta_info, *rta_data; + + if (buflen < sizeof(*req)) + return 0; + memset(req, 0, sizeof(*req)); + + req->n.nlmsg_type = RTM_NEWLINK; + req->n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); + req->n.nlmsg_flags = NLM_F_REQUEST; + + req->ifi.ifi_index = dplane_ctx_get_ifindex(ctx); + req->ifi.ifi_change = 0xFFFFFFFF; + link_idx = dplane_ctx_gre_get_link_ifindex(ctx); + + rta_info = nl_attr_nest(&req->n, buflen, IFLA_LINKINFO); + if (!rta_info) + return 0; + if (!nl_attr_put(&req->n, buflen, IFLA_INFO_KIND, "gre", 3)) + return 0; + rta_data = nl_attr_nest(&req->n, buflen, IFLA_INFO_DATA); + if (!rta_info) + return 0; + if (!nl_attr_put32(&req->n, buflen, IFLA_GRE_LINK, link_idx)) + return 0; + nl_attr_nest_end(&req->n, rta_data); + nl_attr_nest_end(&req->n, rta_info); + + return NLMSG_ALIGN(req->n.nlmsg_len); +} + static int netlink_extract_bridge_info(struct rtattr *link_data, struct zebra_l2info_bridge *bridge_info) { @@ -524,9 +564,13 @@ static int netlink_extract_gre_info(struct rtattr *link_data, if (!attr[IFLA_GRE_LINK]) { if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug("IFLA_GRE_LINK missing from GRE IF message"); - } else + } else { gre_info->ifindex_link = *(ifindex_t *)RTA_DATA(attr[IFLA_GRE_LINK]); + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("IFLA_GRE_LINK obtained is %u", + gre_info->ifindex_link); + } if (attr[IFLA_GRE_IKEY]) gre_info->ikey = *(uint32_t *)RTA_DATA(attr[IFLA_GRE_IKEY]); if (attr[IFLA_GRE_OKEY]) @@ -986,6 +1030,20 @@ static int netlink_request_intf_addr(struct nlsock *netlink_cmd, int family, return netlink_request(netlink_cmd, &req); } +enum netlink_msg_status +netlink_put_gre_set_msg(struct nl_batch *bth, struct zebra_dplane_ctx *ctx) +{ + enum dplane_op_e op; + enum netlink_msg_status ret; + + op = dplane_ctx_get_op(ctx); + assert(op == DPLANE_OP_GRE_SET); + + ret = netlink_batch_add_msg(bth, ctx, netlink_gre_set_msg_encoder, false); + + return ret; +} + /* Interface lookup by netlink socket. */ int interface_lookup_netlink(struct zebra_ns *zns) { diff --git a/zebra/if_netlink.h b/zebra/if_netlink.h index 0bbba81ca6..4f09b10b75 100644 --- a/zebra/if_netlink.h +++ b/zebra/if_netlink.h @@ -32,6 +32,9 @@ extern int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id, extern int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup); extern int interface_lookup_netlink(struct zebra_ns *zns); +extern enum netlink_msg_status +netlink_put_gre_set_msg(struct nl_batch *bth, struct zebra_dplane_ctx *ctx); + extern enum netlink_msg_status netlink_put_address_update_msg(struct nl_batch *bth, struct zebra_dplane_ctx *ctx); diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c index adb61023c1..cd22e95737 100644 --- a/zebra/kernel_netlink.c +++ b/zebra/kernel_netlink.c @@ -1360,6 +1360,9 @@ static enum netlink_msg_status nl_put_msg(struct nl_batch *bth, case DPLANE_OP_IPSET_ENTRY_DELETE: return FRR_NETLINK_ERROR; + case DPLANE_OP_GRE_SET: + return netlink_put_gre_set_msg(bth, ctx); + case DPLANE_OP_NONE: return FRR_NETLINK_ERROR; } diff --git a/zebra/rt.h b/zebra/rt.h index daaa926a7d..f79ddbe958 100644 --- a/zebra/rt.h +++ b/zebra/rt.h @@ -81,9 +81,6 @@ extern int mpls_kernel_init(void); extern uint32_t kernel_get_speed(struct interface *ifp, int *error); extern int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *mroute); -extern int kernel_configure_if_link(struct interface *ifp, - struct interface *link_ifp, ns_id_t ns_id); - /* * Southbound Initialization routines to get initial starting * state. diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index d8405f277e..d2ec7da57c 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -3890,14 +3890,6 @@ netlink_put_neigh_update_msg(struct nl_batch *bth, struct zebra_dplane_ctx *ctx) false); } -int kernel_configure_if_link(struct interface *ifp, - struct interface *link_ifp, - ns_id_t ns_id) -{ - /* TODO */ - return 0; -} - /* * MPLS label forwarding table change via netlink interface, using dataplane * context information. diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c index ada828d016..006513ac9e 100644 --- a/zebra/rt_socket.c +++ b/zebra/rt_socket.c @@ -394,12 +394,6 @@ enum zebra_dplane_result kernel_mac_update_ctx(struct zebra_dplane_ctx *ctx) return ZEBRA_DPLANE_REQUEST_SUCCESS; } -int kernel_configure_if_link(struct interface *ifp, struct interface *link_ifp, - ns_id_t ns_id) -{ - return 0; -} - extern int kernel_interface_set_master(struct interface *master, struct interface *slave) { diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index d36c6becd7..22a6bf496b 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -3435,22 +3435,40 @@ static inline void zebra_gre_source_set(ZAPI_HANDLER_ARGS) vrf_id_t link_vrf_id; struct interface *ifp; struct interface *ifp_link; - ns_id_t ns_id; vrf_id_t vrf_id = zvrf->vrf->vrf_id; + struct zebra_if *zif, *gre_zif; + struct zebra_l2info_gre *gre_info; s = msg; STREAM_GETL(s, idx); ifp = if_lookup_by_index(idx, vrf_id); STREAM_GETL(s, link_idx); STREAM_GETL(s, link_vrf_id); + ifp_link = if_lookup_by_index(link_idx, link_vrf_id); if (!ifp_link || !ifp) { zlog_warn("GRE (index %u, VRF %u) or GRE link interface (index %u, VRF %u) not found, when setting GRE params", idx, vrf_id, link_idx, link_vrf_id); return; } - ns_id = zvrf->zns->ns_id; - kernel_configure_if_link(ifp, ifp_link, ns_id); + + if (!IS_ZEBRA_IF_GRE(ifp)) + return; + + gre_zif = (struct zebra_if *)ifp->info; + zif = (struct zebra_if *)ifp_link->info; + if (!zif || !gre_zif) + return; + + gre_info = &zif->l2info.gre; + if (!gre_info) + return; + + /* if gre link already set */ + if (gre_zif->link && gre_zif->link == ifp_link) + return; + + dplane_gre_set(ifp, ifp_link); stream_failure: return; diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c index c8ee8f9051..565ab821df 100644 --- a/zebra/zebra_dplane.c +++ b/zebra/zebra_dplane.c @@ -271,6 +271,9 @@ struct dplane_rule_info { struct dplane_ctx_rule old; }; +struct dplane_gre_ctx { + uint32_t link_ifindex; +}; /* * The context block used to exchange info about route updates across * the boundary between the zebra main context (and pthread) and the @@ -327,6 +330,7 @@ struct zebra_dplane_ctx { struct zebra_pbr_ipset_info info; } ipset_entry; struct dplane_neigh_table neightable; + struct dplane_gre_ctx gre; } u; /* Namespace info, used especially for netlink kernel communication */ @@ -469,6 +473,9 @@ static struct zebra_dplane_globals { _Atomic uint32_t dg_neightable_in; _Atomic uint32_t dg_neightable_errors; + _Atomic uint32_t dg_gre_set_in; + _Atomic uint32_t dg_gre_set_errors; + /* Dataplane pthread */ struct frr_pthread *dg_pthread; @@ -713,6 +720,9 @@ static void dplane_ctx_free_internal(struct zebra_dplane_ctx *ctx) } list_delete(&ctx->u.iptable.interface_name_list); } + break; + case DPLANE_OP_GRE_SET: + break; } } @@ -979,6 +989,10 @@ const char *dplane_op2str(enum dplane_op_e op) case DPLANE_OP_NEIGH_TABLE_UPDATE: ret = "NEIGH_TABLE_UPDATE"; break; + + case DPLANE_OP_GRE_SET: + ret = "GRE_SET"; + break; } return ret; @@ -1772,6 +1786,15 @@ uint32_t dplane_ctx_neigh_get_update_flags(const struct zebra_dplane_ctx *ctx) return ctx->u.neigh.update_flags; } +/* Accessor for GRE set */ +uint32_t +dplane_ctx_gre_get_link_ifindex(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->u.gre.link_ifindex; +} + /* Accessors for PBR rule information */ int dplane_ctx_rule_get_sock(const struct zebra_dplane_ctx *ctx) { @@ -4125,6 +4148,67 @@ dplane_pbr_ipset_entry_delete(struct zebra_pbr_ipset_entry *ipset) return ipset_entry_update_internal(DPLANE_OP_IPSET_ENTRY_DELETE, ipset); } +/* + * Common helper api for GRE set + */ +enum zebra_dplane_result +dplane_gre_set(struct interface *ifp, struct interface *ifp_link) +{ + enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE; + struct zebra_dplane_ctx *ctx; + enum dplane_op_e op = DPLANE_OP_GRE_SET; + int ret; + struct zebra_ns *zns; + + ctx = dplane_ctx_alloc(); + + if (!ifp) + return result; + + if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) { + zlog_debug("init dplane ctx %s: if %s link %s%s", + dplane_op2str(op), ifp->name, + ifp_link ? "set" : "unset", ifp_link ? + ifp_link->name : ""); + } + + ctx->zd_op = op; + ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS; + zns = zebra_ns_lookup(ifp->vrf_id); + if (!zns) + return result; + dplane_ctx_ns_init(ctx, zns, false); + + dplane_ctx_set_ifname(ctx, ifp->name); + ctx->zd_vrf_id = ifp->vrf_id; + ctx->zd_ifindex = ifp->ifindex; + if (ifp_link) + ctx->u.gre.link_ifindex = ifp_link->ifindex; + else + ctx->u.gre.link_ifindex = 0; + + ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS; + + /* Enqueue context for processing */ + ret = dplane_update_enqueue(ctx); + + /* Update counter */ + atomic_fetch_add_explicit(&zdplane_info.dg_gre_set_in, 1, + memory_order_relaxed); + + if (ret == AOK) + result = ZEBRA_DPLANE_REQUEST_QUEUED; + else { + atomic_fetch_add_explicit( + &zdplane_info.dg_gre_set_errors, 1, + memory_order_relaxed); + if (ctx) + dplane_ctx_free(&ctx); + result = ZEBRA_DPLANE_REQUEST_FAILURE; + } + return result; +} + /* * Handler for 'show dplane' */ @@ -4234,6 +4318,13 @@ int dplane_show_helper(struct vty *vty, bool detailed) memory_order_relaxed); vty_out(vty, "Neighbor Table updates: %"PRIu64"\n", incoming); vty_out(vty, "Neighbor Table errors: %"PRIu64"\n", errs); + + incoming = atomic_load_explicit(&zdplane_info.dg_gre_set_in, + memory_order_relaxed); + errs = atomic_load_explicit(&zdplane_info.dg_gre_set_errors, + memory_order_relaxed); + vty_out(vty, "GRE set updates: %"PRIu64"\n", incoming); + vty_out(vty, "GRE set errors: %"PRIu64"\n", errs); return CMD_SUCCESS; } @@ -4680,6 +4771,12 @@ static void kernel_dplane_log_detail(struct zebra_dplane_ctx *ctx) dplane_ctx_get_ifname(ctx), family2str(dplane_ctx_neightable_get_family(ctx))); break; + case DPLANE_OP_GRE_SET: + zlog_debug("Dplane gre set op %s, ifp %s, link %u", + dplane_op2str(dplane_ctx_get_op(ctx)), + dplane_ctx_get_ifname(ctx), + ctx->u.gre.link_ifindex); + break; } } @@ -4808,6 +4905,12 @@ static void kernel_dplane_handle_result(struct zebra_dplane_ctx *ctx) memory_order_relaxed); break; + case DPLANE_OP_GRE_SET: + if (res != ZEBRA_DPLANE_REQUEST_SUCCESS) + atomic_fetch_add_explicit( + &zdplane_info.dg_gre_set_errors, 1, + memory_order_relaxed); + break; /* Ignore 'notifications' - no-op */ case DPLANE_OP_SYS_ROUTE_ADD: case DPLANE_OP_SYS_ROUTE_DELETE: diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h index 8d51d93cd4..5df58e6e99 100644 --- a/zebra/zebra_dplane.h +++ b/zebra/zebra_dplane.h @@ -171,6 +171,7 @@ enum dplane_op_e { DPLANE_OP_NEIGH_IP_DELETE, DPLANE_OP_NEIGH_TABLE_UPDATE, + DPLANE_OP_GRE_SET, }; /* @@ -527,6 +528,10 @@ dplane_ctx_neightable_get_mcast_probes(const struct zebra_dplane_ctx *ctx); uint32_t dplane_ctx_neightable_get_ucast_probes(const struct zebra_dplane_ctx *ctx); +/* Accessor for GRE set */ +uint32_t +dplane_ctx_gre_get_link_ifindex(const struct zebra_dplane_ctx *ctx); + /* Namespace info - esp. for netlink communication */ const struct zebra_dplane_info *dplane_ctx_get_ns( const struct zebra_dplane_ctx *ctx); @@ -695,6 +700,12 @@ enum zebra_dplane_result dplane_neigh_table_update(const struct interface *ifp, const uint32_t ucast_probes, const uint32_t mcast_probes); +/* + * Enqueue a GRE set + */ +enum zebra_dplane_result +dplane_gre_set(struct interface *ifp, struct interface *ifp_link); + /* Forward ref of zebra_pbr_rule */ struct zebra_pbr_rule; diff --git a/zebra/zebra_errors.h b/zebra/zebra_errors.h index fc0382a6cd..200a977a69 100644 --- a/zebra/zebra_errors.h +++ b/zebra/zebra_errors.h @@ -134,6 +134,7 @@ enum zebra_log_refs { EC_ZEBRA_DUPLICATE_NHG_MESSAGE, EC_ZEBRA_VRF_MISCONFIGURED, EC_ZEBRA_ES_CREATE, + EC_ZEBRA_GRE_SET_UPDATE, }; void zebra_error_init(void); diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c index 47651318a4..6b40eae5b7 100644 --- a/zebra/zebra_nhg.c +++ b/zebra/zebra_nhg.c @@ -2965,6 +2965,7 @@ void zebra_nhg_dplane_result(struct zebra_dplane_ctx *ctx) case DPLANE_OP_IPSET_ENTRY_ADD: case DPLANE_OP_IPSET_ENTRY_DELETE: case DPLANE_OP_NEIGH_TABLE_UPDATE: + case DPLANE_OP_GRE_SET: break; } diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index bdacd411bd..dbc5c77fd9 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -4062,6 +4062,7 @@ static int rib_process_dplane_results(struct thread *thread) case DPLANE_OP_NEIGH_DISCOVER: case DPLANE_OP_BR_PORT_UPDATE: case DPLANE_OP_NEIGH_TABLE_UPDATE: + case DPLANE_OP_GRE_SET: case DPLANE_OP_NONE: /* Don't expect this: just return the struct? */ dplane_ctx_fini(&ctx); From db51f0cd10709079c73b68e6abe9bed0785f2137 Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Thu, 11 Mar 2021 16:01:10 +0100 Subject: [PATCH 09/11] nhrp: Preserve mtu during interface up/down and tunnel source change preserve mtu upon interface flapping and tunnel source change. Signed-off-by:Reuben Dowle Signed-off-by: Philippe Guibert --- nhrpd/nhrp_route.c | 1 + zebra/if_netlink.c | 5 +++++ zebra/zapi_msg.c | 11 ++++++++--- zebra/zebra_dplane.c | 13 ++++++++++++- zebra/zebra_dplane.h | 5 ++++- 5 files changed, 30 insertions(+), 5 deletions(-) diff --git a/nhrpd/nhrp_route.c b/nhrpd/nhrp_route.c index 1f513b7c0e..ee8db277d9 100644 --- a/nhrpd/nhrp_route.c +++ b/nhrpd/nhrp_route.c @@ -435,6 +435,7 @@ void nhrp_send_zebra_gre_source_set(struct interface *ifp, stream_putl(s, ifp->ifindex); stream_putl(s, link_idx); stream_putl(s, link_vrf_id); + stream_putl(s, 0); /* mtu provisioning */ stream_putw_at(s, 0, stream_get_endp(s)); zclient_send_message(zclient); } diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index 44ee8d9469..1886f7a542 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -473,6 +473,7 @@ netlink_gre_set_msg_encoder(struct zebra_dplane_ctx *ctx, void *buf, char buf[]; } *req = buf; uint32_t link_idx; + unsigned int mtu; struct rtattr *rta_info, *rta_data; if (buflen < sizeof(*req)) @@ -486,6 +487,10 @@ netlink_gre_set_msg_encoder(struct zebra_dplane_ctx *ctx, void *buf, req->ifi.ifi_index = dplane_ctx_get_ifindex(ctx); req->ifi.ifi_change = 0xFFFFFFFF; link_idx = dplane_ctx_gre_get_link_ifindex(ctx); + mtu = dplane_ctx_gre_get_mtu(ctx); + + if (mtu && !nl_attr_put32(&req->n, buflen, IFLA_MTU, mtu)) + return 0; rta_info = nl_attr_nest(&req->n, buflen, IFLA_LINKINFO); if (!rta_info) diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 22a6bf496b..75e2f59b98 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -3438,12 +3438,14 @@ static inline void zebra_gre_source_set(ZAPI_HANDLER_ARGS) vrf_id_t vrf_id = zvrf->vrf->vrf_id; struct zebra_if *zif, *gre_zif; struct zebra_l2info_gre *gre_info; + unsigned int mtu; s = msg; STREAM_GETL(s, idx); ifp = if_lookup_by_index(idx, vrf_id); STREAM_GETL(s, link_idx); STREAM_GETL(s, link_vrf_id); + STREAM_GETL(s, mtu); ifp_link = if_lookup_by_index(link_idx, link_vrf_id); if (!ifp_link || !ifp) { @@ -3464,11 +3466,14 @@ static inline void zebra_gre_source_set(ZAPI_HANDLER_ARGS) if (!gre_info) return; - /* if gre link already set */ - if (gre_zif->link && gre_zif->link == ifp_link) + if (!mtu) + mtu = ifp->mtu; + + /* if gre link already set or mtu did not change, do not set it */ + if (gre_zif->link && gre_zif->link == ifp_link && mtu == ifp->mtu) return; - dplane_gre_set(ifp, ifp_link); + dplane_gre_set(ifp, ifp_link, mtu); stream_failure: return; diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c index 565ab821df..b54973a941 100644 --- a/zebra/zebra_dplane.c +++ b/zebra/zebra_dplane.c @@ -273,6 +273,7 @@ struct dplane_rule_info { struct dplane_gre_ctx { uint32_t link_ifindex; + unsigned int mtu; }; /* * The context block used to exchange info about route updates across @@ -1795,6 +1796,14 @@ dplane_ctx_gre_get_link_ifindex(const struct zebra_dplane_ctx *ctx) return ctx->u.gre.link_ifindex; } +unsigned int +dplane_ctx_gre_get_mtu(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->u.gre.mtu; +} + /* Accessors for PBR rule information */ int dplane_ctx_rule_get_sock(const struct zebra_dplane_ctx *ctx) { @@ -4152,7 +4161,7 @@ dplane_pbr_ipset_entry_delete(struct zebra_pbr_ipset_entry *ipset) * Common helper api for GRE set */ enum zebra_dplane_result -dplane_gre_set(struct interface *ifp, struct interface *ifp_link) +dplane_gre_set(struct interface *ifp, struct interface *ifp_link, unsigned int mtu) { enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE; struct zebra_dplane_ctx *ctx; @@ -4187,6 +4196,8 @@ dplane_gre_set(struct interface *ifp, struct interface *ifp_link) else ctx->u.gre.link_ifindex = 0; + ctx->u.gre.mtu = mtu; + ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS; /* Enqueue context for processing */ diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h index 5df58e6e99..5405a7cb85 100644 --- a/zebra/zebra_dplane.h +++ b/zebra/zebra_dplane.h @@ -531,6 +531,8 @@ dplane_ctx_neightable_get_ucast_probes(const struct zebra_dplane_ctx *ctx); /* Accessor for GRE set */ uint32_t dplane_ctx_gre_get_link_ifindex(const struct zebra_dplane_ctx *ctx); +unsigned int +dplane_ctx_gre_get_mtu(const struct zebra_dplane_ctx *ctx); /* Namespace info - esp. for netlink communication */ const struct zebra_dplane_info *dplane_ctx_get_ns( @@ -704,7 +706,8 @@ enum zebra_dplane_result dplane_neigh_table_update(const struct interface *ifp, * Enqueue a GRE set */ enum zebra_dplane_result -dplane_gre_set(struct interface *ifp, struct interface *ifp_link); +dplane_gre_set(struct interface *ifp, struct interface *ifp_link, + unsigned int mtu); /* Forward ref of zebra_pbr_rule */ struct zebra_pbr_rule; From e3d3fa06f735dc00d406dc03d7fb84eabaf07b87 Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Fri, 12 Mar 2021 14:32:53 +0100 Subject: [PATCH 10/11] zebra: collect gre information and push it when needed - gre keys are collected and stored locally. - when gre source set is requested, and the link interface configured is different, the gre information collected is pushed in the query, namely source ip or gre keys if present. Signed-off-by: Philippe Guibert --- zebra/if_netlink.c | 32 +++++++++++++++++++++++++++++++- zebra/zapi_msg.c | 2 +- zebra/zebra_dplane.c | 15 +++++++++++++-- zebra/zebra_dplane.h | 4 +++- 4 files changed, 48 insertions(+), 5 deletions(-) diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index 1886f7a542..b1e0f21f68 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -73,6 +73,7 @@ #include "zebra/zebra_errors.h" #include "zebra/zebra_vxlan.h" #include "zebra/zebra_evpn_mh.h" +#include "zebra/zebra_l2.h" extern struct zebra_privs_t zserv_privs; @@ -475,6 +476,7 @@ netlink_gre_set_msg_encoder(struct zebra_dplane_ctx *ctx, void *buf, uint32_t link_idx; unsigned int mtu; struct rtattr *rta_info, *rta_data; + const struct zebra_l2info_gre *gre_info; if (buflen < sizeof(*req)) return 0; @@ -485,6 +487,11 @@ netlink_gre_set_msg_encoder(struct zebra_dplane_ctx *ctx, void *buf, req->n.nlmsg_flags = NLM_F_REQUEST; req->ifi.ifi_index = dplane_ctx_get_ifindex(ctx); + + gre_info = dplane_ctx_gre_get_info(ctx); + if (!gre_info) + return 0; + req->ifi.ifi_change = 0xFFFFFFFF; link_idx = dplane_ctx_gre_get_link_ifindex(ctx); mtu = dplane_ctx_gre_get_mtu(ctx); @@ -495,13 +502,36 @@ netlink_gre_set_msg_encoder(struct zebra_dplane_ctx *ctx, void *buf, rta_info = nl_attr_nest(&req->n, buflen, IFLA_LINKINFO); if (!rta_info) return 0; + if (!nl_attr_put(&req->n, buflen, IFLA_INFO_KIND, "gre", 3)) return 0; + rta_data = nl_attr_nest(&req->n, buflen, IFLA_INFO_DATA); - if (!rta_info) + if (!rta_data) return 0; + if (!nl_attr_put32(&req->n, buflen, IFLA_GRE_LINK, link_idx)) return 0; + + if (gre_info->vtep_ip.s_addr && + !nl_attr_put32(&req->n, buflen, IFLA_GRE_LOCAL, + gre_info->vtep_ip.s_addr)) + return 0; + + if (gre_info->vtep_ip_remote.s_addr && + !nl_attr_put32(&req->n, buflen, IFLA_GRE_REMOTE, + gre_info->vtep_ip_remote.s_addr)) + return 0; + + if (gre_info->ikey && + !nl_attr_put32(&req->n, buflen, IFLA_GRE_IKEY, + gre_info->ikey)) + return 0; + if (gre_info->okey && + !nl_attr_put32(&req->n, buflen, IFLA_GRE_IKEY, + gre_info->okey)) + return 0; + nl_attr_nest_end(&req->n, rta_data); nl_attr_nest_end(&req->n, rta_info); diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 75e2f59b98..55f8edd272 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -3473,7 +3473,7 @@ static inline void zebra_gre_source_set(ZAPI_HANDLER_ARGS) if (gre_zif->link && gre_zif->link == ifp_link && mtu == ifp->mtu) return; - dplane_gre_set(ifp, ifp_link, mtu); + dplane_gre_set(ifp, ifp_link, mtu, gre_info); stream_failure: return; diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c index b54973a941..a8df0c56ce 100644 --- a/zebra/zebra_dplane.c +++ b/zebra/zebra_dplane.c @@ -274,6 +274,7 @@ struct dplane_rule_info { struct dplane_gre_ctx { uint32_t link_ifindex; unsigned int mtu; + struct zebra_l2info_gre info; }; /* * The context block used to exchange info about route updates across @@ -1804,6 +1805,14 @@ dplane_ctx_gre_get_mtu(const struct zebra_dplane_ctx *ctx) return ctx->u.gre.mtu; } +const struct zebra_l2info_gre * +dplane_ctx_gre_get_info(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return &ctx->u.gre.info; +} + /* Accessors for PBR rule information */ int dplane_ctx_rule_get_sock(const struct zebra_dplane_ctx *ctx) { @@ -4161,7 +4170,8 @@ dplane_pbr_ipset_entry_delete(struct zebra_pbr_ipset_entry *ipset) * Common helper api for GRE set */ enum zebra_dplane_result -dplane_gre_set(struct interface *ifp, struct interface *ifp_link, unsigned int mtu) +dplane_gre_set(struct interface *ifp, struct interface *ifp_link, + unsigned int mtu, const struct zebra_l2info_gre *gre_info) { enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE; struct zebra_dplane_ctx *ctx; @@ -4195,7 +4205,8 @@ dplane_gre_set(struct interface *ifp, struct interface *ifp_link, unsigned int m ctx->u.gre.link_ifindex = ifp_link->ifindex; else ctx->u.gre.link_ifindex = 0; - + if (gre_info) + memcpy(&ctx->u.gre.info, gre_info, sizeof(ctx->u.gre.info)); ctx->u.gre.mtu = mtu; ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS; diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h index 5405a7cb85..3a8536dda5 100644 --- a/zebra/zebra_dplane.h +++ b/zebra/zebra_dplane.h @@ -533,6 +533,8 @@ uint32_t dplane_ctx_gre_get_link_ifindex(const struct zebra_dplane_ctx *ctx); unsigned int dplane_ctx_gre_get_mtu(const struct zebra_dplane_ctx *ctx); +const struct zebra_l2info_gre * +dplane_ctx_gre_get_info(const struct zebra_dplane_ctx *ctx); /* Namespace info - esp. for netlink communication */ const struct zebra_dplane_info *dplane_ctx_get_ns( @@ -707,7 +709,7 @@ enum zebra_dplane_result dplane_neigh_table_update(const struct interface *ifp, */ enum zebra_dplane_result dplane_gre_set(struct interface *ifp, struct interface *ifp_link, - unsigned int mtu); + unsigned int mtu, const struct zebra_l2info_gre *gre_info); /* Forward ref of zebra_pbr_rule */ struct zebra_pbr_rule; From dee1c6c3384ca9f22f2920263640f4c4dc9eb67c Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Fri, 16 Apr 2021 17:18:02 +0200 Subject: [PATCH 11/11] nhrpd: move prototype to top of file nhrp prototype function was not declared at top of the file. fixing it. Signed-off-by: Philippe Guibert --- nhrpd/nhrp_interface.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nhrpd/nhrp_interface.c b/nhrpd/nhrp_interface.c index 541e5a992a..2db8997bad 100644 --- a/nhrpd/nhrp_interface.c +++ b/nhrpd/nhrp_interface.c @@ -26,6 +26,10 @@ DEFINE_MTYPE_STATIC(NHRPD, NHRP_IF_GRE, "NHRP GRE interface"); struct hash *nhrp_gre_list; +static void nhrp_interface_update_cache_config(struct interface *ifp, + bool available, + uint8_t family); + static unsigned int nhrp_gre_info_key(const void *data) { const struct nhrp_gre_info *r = data; @@ -61,10 +65,6 @@ struct nhrp_gre_info *nhrp_gre_info_alloc(struct nhrp_gre_info *p) return a; } -static void nhrp_interface_update_cache_config(struct interface *ifp, - bool available, - uint8_t family); - static int nhrp_if_new_hook(struct interface *ifp) { struct nhrp_interface *nifp;