diff --git a/zebra/label_manager.c b/zebra/label_manager.c index 38869e80ec..190ac1e57f 100644 --- a/zebra/label_manager.c +++ b/zebra/label_manager.c @@ -235,6 +235,40 @@ static void lm_zclient_init(char *lm_zserv_path) lm_zclient_connect(NULL); } +/** + * Release label chunks from a client. + * + * Called on client disconnection or reconnection. It only releases chunks + * with empty keep value. + * + * @param proto Daemon protocol of client, to identify the owner + * @param instance Instance, to identify the owner + * @return Number of chunks released + */ +int release_daemon_label_chunks(struct zserv *client) +{ + uint8_t proto = client->proto; + uint16_t instance = client->instance; + struct listnode *node; + struct label_manager_chunk *lmc; + int count = 0; + int ret; + + for (ALL_LIST_ELEMENTS_RO(lbl_mgr.lc_list, node, lmc)) { + if (lmc->proto == proto && lmc->instance == instance + && lmc->keep == 0) { + ret = release_label_chunk(lmc->proto, lmc->instance, + lmc->start, lmc->end); + if (ret == 0) + count++; + } + } + + zlog_debug("%s: Released %d label chunks", __func__, count); + + return count; +} + /** * Init label manager (or proxy to an external one) */ @@ -255,6 +289,8 @@ void label_manager_init(char *lm_zserv_path) ibuf = stream_new(ZEBRA_MAX_PACKET_SIZ); obuf = stream_new(ZEBRA_MAX_PACKET_SIZ); + + hook_register(zapi_client_close, release_daemon_label_chunks); } /** @@ -353,37 +389,6 @@ int release_label_chunk(uint8_t proto, unsigned short instance, uint32_t start, return ret; } -/** - * Release label chunks from a client. - * - * Called on client disconnection or reconnection. It only releases chunks - * with empty keep value. - * - * @param proto Daemon protocol of client, to identify the owner - * @param instance Instance, to identify the owner - * @return Number of chunks released - */ -int release_daemon_label_chunks(uint8_t proto, unsigned short instance) -{ - struct listnode *node; - struct label_manager_chunk *lmc; - int count = 0; - int ret; - - for (ALL_LIST_ELEMENTS_RO(lbl_mgr.lc_list, node, lmc)) { - if (lmc->proto == proto && lmc->instance == instance - && lmc->keep == 0) { - ret = release_label_chunk(lmc->proto, lmc->instance, - lmc->start, lmc->end); - if (ret == 0) - count++; - } - } - - zlog_debug("%s: Released %d label chunks", __func__, count); - - return count; -} void label_manager_close() { diff --git a/zebra/label_manager.h b/zebra/label_manager.h index 4395e6897e..b998372224 100644 --- a/zebra/label_manager.h +++ b/zebra/label_manager.h @@ -29,6 +29,8 @@ #include "lib/linklist.h" #include "lib/thread.h" +#include "zebra/zserv.h" + #define NO_PROTO 0 /* @@ -69,7 +71,7 @@ struct label_manager_chunk *assign_label_chunk(uint8_t proto, uint8_t keep, uint32_t size); int release_label_chunk(uint8_t proto, unsigned short instance, uint32_t start, uint32_t end); -int release_daemon_label_chunks(uint8_t proto, unsigned short instance); +int release_daemon_label_chunks(struct zserv *client); void label_manager_close(void); #endif /* _LABEL_MANAGER_H */ diff --git a/zebra/main.c b/zebra/main.c index c8d7f83fb7..9a495c8940 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -36,6 +36,7 @@ #include "vrf.h" #include "logicalrouter.h" #include "libfrr.h" +#include "routemap.h" #include "zebra/rib.h" #include "zebra/zserv.h" @@ -49,6 +50,7 @@ #include "zebra/zebra_mpls.h" #include "zebra/label_manager.h" #include "zebra/zebra_netns_notify.h" +#include "zebra/zebra_rnh.h" #define ZEBRA_PTM_SUPPORT @@ -371,6 +373,9 @@ int main(int argc, char **argv) /* Init label manager */ label_manager_init(lblmgr_path); + /* RNH init */ + zebra_rnh_init(); + frr_run(zebrad.master); /* Not reached... */ diff --git a/zebra/redistribute.c b/zebra/redistribute.c index 1d66653e74..810ee33839 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -40,6 +40,7 @@ #include "zebra/redistribute.h" #include "zebra/debug.h" #include "zebra/router-id.h" +#include "zebra/zapi_msg.h" #include "zebra/zebra_memory.h" #include "zebra/zebra_vxlan.h" diff --git a/zebra/redistribute.h b/zebra/redistribute.h index c78480d9a3..9b4820acd4 100644 --- a/zebra/redistribute.h +++ b/zebra/redistribute.h @@ -23,10 +23,12 @@ #define _ZEBRA_REDISTRIBUTE_H #include "table.h" -#include "zserv.h" #include "vty.h" #include "vrf.h" +#include "zebra/zserv.h" +#include "zebra/rib.h" + /* ZAPI command handlers */ extern void zebra_redistribute_add(ZAPI_HANDLER_ARGS); extern void zebra_redistribute_delete(ZAPI_HANDLER_ARGS); diff --git a/zebra/router-id.c b/zebra/router-id.c index f6c88a2162..252b558a8b 100644 --- a/zebra/router-id.c +++ b/zebra/router-id.c @@ -39,6 +39,7 @@ #include "vrf.h" #include "zebra/zserv.h" +#include "zebra/zapi_msg.h" #include "zebra/zebra_vrf.h" #include "zebra/router-id.h" #include "zebra/redistribute.h" diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index e68e3aaafd..cdc52211cc 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -50,7 +50,7 @@ #include "mpls.h" #include "vxlan.h" -#include "zebra/zserv.h" +#include "zebra/zapi_msg.h" #include "zebra/zebra_ns.h" #include "zebra/zebra_vrf.h" #include "zebra/rt.h" diff --git a/zebra/rtadv.c b/zebra/rtadv.c index c695b65660..dc918b1a9b 100644 --- a/zebra/rtadv.c +++ b/zebra/rtadv.c @@ -40,7 +40,7 @@ #include "zebra/rtadv.h" #include "zebra/debug.h" #include "zebra/rib.h" -#include "zebra/zserv.h" +#include "zebra/zapi_msg.h" #include "zebra/zebra_ns.h" #include "zebra/zebra_vrf.h" diff --git a/zebra/subdir.am b/zebra/subdir.am index 9dbff7d40c..45e285a9e7 100644 --- a/zebra/subdir.am +++ b/zebra/subdir.am @@ -71,6 +71,7 @@ zebra_zebra_SOURCES = \ zebra/zebra_netns_id.c \ zebra/zebra_netns_notify.c \ zebra/table_manager.c \ + zebra/zapi_msg.c \ # end zebra/zebra_vty_clippy.c: $(CLIPPY_DEPS) @@ -115,6 +116,7 @@ noinst_HEADERS += \ zebra/zebra_netns_id.h \ zebra/zebra_netns_notify.h \ zebra/table_manager.h \ + zebra/zapi_msg.h \ # end zebra_zebra_irdp_la_SOURCES = \ diff --git a/zebra/table_manager.c b/zebra/table_manager.c index db07f402f3..cb8c384436 100644 --- a/zebra/table_manager.c +++ b/zebra/table_manager.c @@ -16,12 +16,12 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "zebra.h" + #include #include #include -#include "zebra.h" -#include "zserv.h" #include "lib/log.h" #include "lib/memory.h" #include "lib/table.h" @@ -31,9 +31,10 @@ #include "lib/libfrr.h" #include "lib/vrf.h" -#include "zebra_vrf.h" -#include "label_manager.h" /* for NO_PROTO */ -#include "table_manager.h" +#include "zebra/zserv.h" +#include "zebra/zebra_vrf.h" +#include "zebra/label_manager.h" /* for NO_PROTO */ +#include "zebra/table_manager.h" /* routing table identifiers * @@ -77,6 +78,7 @@ void table_manager_enable(ns_id_t ns_id) return; tbl_mgr.lc_list = list_new(); tbl_mgr.lc_list->del = delete_table_chunk; + hook_register(zapi_client_close, release_daemon_table_chunks); } /** @@ -202,12 +204,13 @@ int release_table_chunk(uint8_t proto, uint16_t instance, uint32_t start, * Called on client disconnection or reconnection. It only releases chunks * with empty keep value. * - * @param proto Daemon protocol of client, to identify the owner - * @param instance Instance, to identify the owner + * @param client the client to release chunks from * @return Number of chunks released */ -int release_daemon_table_chunks(uint8_t proto, uint16_t instance) +int release_daemon_table_chunks(struct zserv *client) { + uint8_t proto = client->proto; + uint16_t instance = client->instance; struct listnode *node; struct table_manager_chunk *tmc; int count = 0; diff --git a/zebra/table_manager.h b/zebra/table_manager.h index 527d5c29e8..5196162c4c 100644 --- a/zebra/table_manager.h +++ b/zebra/table_manager.h @@ -23,6 +23,9 @@ #include "lib/linklist.h" #include "lib/thread.h" +#include "lib/ns.h" + +#include "zebra/zserv.h" /* * Table chunk struct @@ -57,7 +60,7 @@ struct table_manager_chunk *assign_table_chunk(uint8_t proto, uint16_t instance, uint32_t size); int release_table_chunk(uint8_t proto, uint16_t instance, uint32_t start, uint32_t end); -int release_daemon_table_chunks(uint8_t proto, uint16_t instance); +int release_daemon_table_chunks(struct zserv *client); void table_manager_disable(ns_id_t ns_id); #endif /* _TABLE_MANAGER_H */ diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c new file mode 100644 index 0000000000..2ff660b3f9 --- /dev/null +++ b/zebra/zapi_msg.c @@ -0,0 +1,2961 @@ +/* + * Zebra API message creation & consumption. + * Portions: + * Copyright (C) 1997-1999 Kunihiro Ishiguro + * Copyright (C) 2015-2018 Cumulus Networks, Inc. + * et al. + * + * This program is free software; you can redistribute it 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. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "lib/prefix.h" +#include "lib/command.h" +#include "lib/if.h" +#include "lib/thread.h" +#include "lib/stream.h" +#include "lib/memory.h" +#include "lib/table.h" +#include "lib/network.h" +#include "lib/sockunion.h" +#include "lib/log.h" +#include "lib/zclient.h" +#include "lib/privs.h" +#include "lib/network.h" +#include "lib/buffer.h" +#include "lib/nexthop.h" +#include "lib/vrf.h" +#include "lib/libfrr.h" +#include "lib/sockopt.h" + +#include "zebra/rib.h" +#include "zebra/zebra_memory.h" +#include "zebra/zebra_ns.h" +#include "zebra/zebra_vrf.h" +#include "zebra/router-id.h" +#include "zebra/redistribute.h" +#include "zebra/debug.h" +#include "zebra/zebra_rnh.h" +#include "zebra/rt_netlink.h" +#include "zebra/interface.h" +#include "zebra/zebra_ptm.h" +#include "zebra/rtadv.h" +#include "zebra/zebra_mpls.h" +#include "zebra/zebra_mroute.h" +#include "zebra/label_manager.h" +#include "zebra/zebra_vxlan.h" +#include "zebra/rt.h" +#include "zebra/zebra_pbr.h" +#include "zebra/table_manager.h" +#include "zebra/zapi_msg.h" + +/* Encoding helpers -------------------------------------------------------- */ + +static void zserv_encode_interface(struct stream *s, struct interface *ifp) +{ + /* Interface information. */ + stream_put(s, ifp->name, INTERFACE_NAMSIZ); + stream_putl(s, ifp->ifindex); + stream_putc(s, ifp->status); + stream_putq(s, ifp->flags); + stream_putc(s, ifp->ptm_enable); + stream_putc(s, ifp->ptm_status); + stream_putl(s, ifp->metric); + stream_putl(s, ifp->speed); + stream_putl(s, ifp->mtu); + stream_putl(s, ifp->mtu6); + stream_putl(s, ifp->bandwidth); + stream_putl(s, ifp->ll_type); + stream_putl(s, ifp->hw_addr_len); + if (ifp->hw_addr_len) + stream_put(s, ifp->hw_addr, ifp->hw_addr_len); + + /* Then, Traffic Engineering parameters if any */ + if (HAS_LINK_PARAMS(ifp) && IS_LINK_PARAMS_SET(ifp->link_params)) { + stream_putc(s, 1); + zebra_interface_link_params_write(s, ifp); + } else + stream_putc(s, 0); + + /* Write packet size. */ + stream_putw_at(s, 0, stream_get_endp(s)); +} + +static void zserv_encode_vrf(struct stream *s, struct zebra_vrf *zvrf) +{ + struct vrf_data data; + const char *netns_name = zvrf_ns_name(zvrf); + + data.l.table_id = zvrf->table_id; + + if (netns_name) + strlcpy(data.l.netns_name, basename((char *)netns_name), + NS_NAMSIZ); + else + memset(data.l.netns_name, 0, NS_NAMSIZ); + /* Pass the tableid and the netns NAME */ + stream_put(s, &data, sizeof(struct vrf_data)); + /* Interface information. */ + stream_put(s, zvrf_name(zvrf), VRF_NAMSIZ); + /* Write packet size. */ + stream_putw_at(s, 0, stream_get_endp(s)); +} + +static int zserv_encode_nexthop(struct stream *s, struct nexthop *nexthop) +{ + stream_putc(s, nexthop->type); + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + stream_put_in_addr(s, &nexthop->gate.ipv4); + stream_putl(s, nexthop->ifindex); + break; + case NEXTHOP_TYPE_IPV6: + stream_put(s, &nexthop->gate.ipv6, 16); + break; + case NEXTHOP_TYPE_IPV6_IFINDEX: + stream_put(s, &nexthop->gate.ipv6, 16); + stream_putl(s, nexthop->ifindex); + break; + case NEXTHOP_TYPE_IFINDEX: + stream_putl(s, nexthop->ifindex); + break; + default: + /* do nothing */ + break; + } + return 1; +} + +/* Send handlers ----------------------------------------------------------- */ + +/* Interface is added. Send ZEBRA_INTERFACE_ADD to client. */ +/* + * This function is called in the following situations: + * - in response to a 3-byte ZEBRA_INTERFACE_ADD request + * from the client. + * - at startup, when zebra figures out the available interfaces + * - when an interface is added (where support for + * RTM_IFANNOUNCE or AF_NETLINK sockets is available), or when + * an interface is marked IFF_UP (i.e., an RTM_IFINFO message is + * received) + */ +int zsend_interface_add(struct zserv *client, struct interface *ifp) +{ + struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ); + + zclient_create_header(s, ZEBRA_INTERFACE_ADD, ifp->vrf_id); + zserv_encode_interface(s, ifp); + + client->ifadd_cnt++; + return zebra_server_send_message(client, s); +} + +/* Interface deletion from zebra daemon. */ +int zsend_interface_delete(struct zserv *client, struct interface *ifp) +{ + struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ); + + zclient_create_header(s, ZEBRA_INTERFACE_DELETE, ifp->vrf_id); + zserv_encode_interface(s, ifp); + + client->ifdel_cnt++; + return zebra_server_send_message(client, s); +} + +int zsend_vrf_add(struct zserv *client, struct zebra_vrf *zvrf) +{ + struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ); + + zclient_create_header(s, ZEBRA_VRF_ADD, zvrf_id(zvrf)); + zserv_encode_vrf(s, zvrf); + + client->vrfadd_cnt++; + return zebra_server_send_message(client, s); +} + +/* VRF deletion from zebra daemon. */ +int zsend_vrf_delete(struct zserv *client, struct zebra_vrf *zvrf) + +{ + struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ); + + zclient_create_header(s, ZEBRA_VRF_DELETE, zvrf_id(zvrf)); + zserv_encode_vrf(s, zvrf); + + client->vrfdel_cnt++; + return zebra_server_send_message(client, s); +} + +int zsend_interface_link_params(struct zserv *client, struct interface *ifp) +{ + struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ); + + /* Check this client need interface information. */ + if (!client->ifinfo) { + stream_free(s); + return 0; + } + + if (!ifp->link_params) { + stream_free(s); + return 0; + } + + zclient_create_header(s, ZEBRA_INTERFACE_LINK_PARAMS, ifp->vrf_id); + + /* Add Interface Index */ + stream_putl(s, ifp->ifindex); + + /* Then TE Link Parameters */ + if (zebra_interface_link_params_write(s, ifp) == 0) { + stream_free(s); + return 0; + } + + /* Write packet size. */ + stream_putw_at(s, 0, stream_get_endp(s)); + + return zebra_server_send_message(client, s); +} + +/* Interface address is added/deleted. Send ZEBRA_INTERFACE_ADDRESS_ADD or + * ZEBRA_INTERFACE_ADDRESS_DELETE to the client. + * + * A ZEBRA_INTERFACE_ADDRESS_ADD is sent in the following situations: + * - in response to a 3-byte ZEBRA_INTERFACE_ADD request + * from the client, after the ZEBRA_INTERFACE_ADD has been + * sent from zebra to the client + * - redistribute new address info to all clients in the following situations + * - at startup, when zebra figures out the available interfaces + * - when an interface is added (where support for + * RTM_IFANNOUNCE or AF_NETLINK sockets is available), or when + * an interface is marked IFF_UP (i.e., an RTM_IFINFO message is + * received) + * - for the vty commands "ip address A.B.C.D/M [|