diff options
| author | ßingen <bingen@voltanet.io> | 2017-05-15 17:09:28 +0200 | 
|---|---|---|
| committer | David Lamparter <equinox@opensourcerouting.org> | 2017-08-09 12:35:15 +0200 | 
| commit | 6833ae01bc8cb0c15579d7098f2d525a6e36c8bb (patch) | |
| tree | f9495c40c9edc6fb7f68bf91a07e56eab003db6e /zebra | |
| parent | 2f9c59f031a76db29235cf17dc6b1e62c39370ac (diff) | |
zebra: add pseudowire manager
Base framework for supporting MPLS pseudowires in FRR.
A consistent zserv interface is provided so that any client daemon
(e.g. ldpd, bgpd) can install/uninstall pseudowires in a standard
way. Static pseudowires can also be implemented by using the same
interface.
When zebra receives a request to install a pseudowire and the installation
in the kernel or hardware fails, a notification is sent back to the
client daemon and a new install attempt is made every 60 seconds (until
it succeeds).
Support for external dataplanes is provided by the use of hooks to
install/uninstall pseudowires.
Signed-off-by: ßingen <bingen@voltanet.io>
Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
Diffstat (limited to 'zebra')
| -rw-r--r-- | zebra/debug.c | 25 | ||||
| -rw-r--r-- | zebra/debug.h | 4 | ||||
| -rw-r--r-- | zebra/subdir.am | 2 | ||||
| -rw-r--r-- | zebra/zebra_pw.c | 268 | ||||
| -rw-r--r-- | zebra/zebra_pw.h | 67 | ||||
| -rw-r--r-- | zebra/zebra_vrf.c | 2 | ||||
| -rw-r--r-- | zebra/zebra_vrf.h | 4 | ||||
| -rw-r--r-- | zebra/zserv.c | 121 | ||||
| -rw-r--r-- | zebra/zserv.h | 3 | 
9 files changed, 496 insertions, 0 deletions
diff --git a/zebra/debug.c b/zebra/debug.c index 6aedea1e39..6728ed1325 100644 --- a/zebra/debug.c +++ b/zebra/debug.c @@ -32,6 +32,7 @@ unsigned long zebra_debug_fpm;  unsigned long zebra_debug_nht;  unsigned long zebra_debug_mpls;  unsigned long zebra_debug_vxlan; +unsigned long zebra_debug_pw;  DEFUN (show_debugging_zebra,         show_debugging_zebra_cmd, @@ -82,6 +83,8 @@ DEFUN (show_debugging_zebra,  		vty_out(vty, "  Zebra next-hop tracking debugging is on\n");  	if (IS_ZEBRA_DEBUG_MPLS)  		vty_out(vty, "  Zebra MPLS debugging is on\n"); +	if (IS_ZEBRA_DEBUG_PW) +		vty_out(vty, "  Zebra pseudowire debugging is on\n");  	return CMD_SUCCESS;  } @@ -130,6 +133,21 @@ DEFUN (debug_zebra_vxlan,  	return CMD_WARNING;  } +DEFUN (debug_zebra_pw, +       debug_zebra_pw_cmd, +       "[no] debug zebra pseudowires", +       "Negate a command or set its defaults\n" +       DEBUG_STR +       "Zebra configuration\n" +       "Debug option set for zebra pseudowires\n") +{ +	if (strmatch(argv[0]->text, "no")) +		UNSET_FLAG(zebra_debug_pw, ZEBRA_DEBUG_PW); +	else +		SET_FLAG(zebra_debug_pw, ZEBRA_DEBUG_PW); +	return CMD_WARNING; +} +  DEFUN (debug_zebra_packet,         debug_zebra_packet_cmd,         "debug zebra packet [<recv|send>] [detail]", @@ -419,6 +437,10 @@ static int config_write_debug(struct vty *vty)  		vty_out(vty, "debug zebra vxlan\n");  		write++;  	} +	if (IS_ZEBRA_DEBUG_PW) { +		vty_out(vty, "debug zebra pseudowires%s", VTY_NEWLINE); +		write++; +	}  	return write;  } @@ -431,6 +453,7 @@ void zebra_debug_init(void)  	zebra_debug_fpm = 0;  	zebra_debug_mpls = 0;  	zebra_debug_vxlan = 0; +	zebra_debug_pw = 0;  	install_node(&debug_node, config_write_debug); @@ -440,6 +463,7 @@ void zebra_debug_init(void)  	install_element(ENABLE_NODE, &debug_zebra_nht_cmd);  	install_element(ENABLE_NODE, &debug_zebra_mpls_cmd);  	install_element(ENABLE_NODE, &debug_zebra_vxlan_cmd); +	install_element(ENABLE_NODE, &debug_zebra_pw_cmd);  	install_element(ENABLE_NODE, &debug_zebra_packet_cmd);  	install_element(ENABLE_NODE, &debug_zebra_kernel_cmd);  	install_element(ENABLE_NODE, &debug_zebra_kernel_msgdump_cmd); @@ -459,6 +483,7 @@ void zebra_debug_init(void)  	install_element(CONFIG_NODE, &debug_zebra_nht_cmd);  	install_element(CONFIG_NODE, &debug_zebra_mpls_cmd);  	install_element(CONFIG_NODE, &debug_zebra_vxlan_cmd); +	install_element(CONFIG_NODE, &debug_zebra_pw_cmd);  	install_element(CONFIG_NODE, &debug_zebra_packet_cmd);  	install_element(CONFIG_NODE, &debug_zebra_kernel_cmd);  	install_element(CONFIG_NODE, &debug_zebra_kernel_msgdump_cmd); diff --git a/zebra/debug.h b/zebra/debug.h index b52bb7d0e9..987f9d0125 100644 --- a/zebra/debug.h +++ b/zebra/debug.h @@ -44,6 +44,8 @@  #define ZEBRA_DEBUG_VXLAN   0x01 +#define ZEBRA_DEBUG_PW      0x01 +  /* Debug related macro. */  #define IS_ZEBRA_DEBUG_EVENT  (zebra_debug_event & ZEBRA_DEBUG_EVENT) @@ -66,6 +68,7 @@  #define IS_ZEBRA_DEBUG_NHT  (zebra_debug_nht & ZEBRA_DEBUG_NHT)  #define IS_ZEBRA_DEBUG_MPLS  (zebra_debug_mpls & ZEBRA_DEBUG_MPLS)  #define IS_ZEBRA_DEBUG_VXLAN (zebra_debug_vxlan & ZEBRA_DEBUG_VXLAN) +#define IS_ZEBRA_DEBUG_PW  (zebra_debug_pw & ZEBRA_DEBUG_PW)  extern unsigned long zebra_debug_event;  extern unsigned long zebra_debug_packet; @@ -75,6 +78,7 @@ extern unsigned long zebra_debug_fpm;  extern unsigned long zebra_debug_nht;  extern unsigned long zebra_debug_mpls;  extern unsigned long zebra_debug_vxlan; +extern unsigned long zebra_debug_pw;  extern void zebra_debug_init(void); diff --git a/zebra/subdir.am b/zebra/subdir.am index ceffa863e9..0391cab9fd 100644 --- a/zebra/subdir.am +++ b/zebra/subdir.am @@ -56,6 +56,7 @@ zebra_zebra_SOURCES = \  	zebra/zebra_ns.c \  	zebra/zebra_ptm.c \  	zebra/zebra_ptm_redistribute.c \ +	zebra/zebra_pw.c \  	zebra/zebra_rib.c \  	zebra/zebra_rnh.c \  	zebra/zebra_routemap.c \ @@ -95,6 +96,7 @@ noinst_HEADERS += \  	zebra/zebra_ns.h \  	zebra/zebra_ptm.h \  	zebra/zebra_ptm_redistribute.h \ +	zebra/zebra_pw.h \  	zebra/zebra_rnh.h \  	zebra/zebra_routemap.h \  	zebra/zebra_static.h \ diff --git a/zebra/zebra_pw.c b/zebra/zebra_pw.c new file mode 100644 index 0000000000..143224254b --- /dev/null +++ b/zebra/zebra_pw.c @@ -0,0 +1,268 @@ +/* Zebra PW code + * Copyright (C) 2016 Volta Networks, Inc. + * + * 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 <zebra.h> + +#include "log.h" +#include "memory.h" +#include "thread.h" +#include "vrf.h" + +#include "zebra/debug.h" +#include "zebra/rib.h" +#include "zebra/zserv.h" +#include "zebra/zebra_vrf.h" +#include "zebra/zebra_pw.h" + +DEFINE_MTYPE_STATIC(LIB, PW, "Pseudowire") + +DEFINE_HOOK(pw_install, (struct zebra_pw * pw), (pw)) +DEFINE_HOOK(pw_uninstall, (struct zebra_pw * pw), (pw)) + +extern struct zebra_t zebrad; + +static void zebra_pw_install(struct zebra_pw *); +static void zebra_pw_uninstall(struct zebra_pw *); +static int zebra_pw_install_retry(struct thread *); +static int zebra_pw_check_reachability(struct zebra_pw *); +static void zebra_pw_update_status(struct zebra_pw *, int); + +static inline int zebra_pw_compare(const struct zebra_pw *a, +				   const struct zebra_pw *b) +{ +	return (strcmp(a->ifname, b->ifname)); +} + +RB_GENERATE(zebra_pw_head, zebra_pw, entry, zebra_pw_compare) + +struct zebra_pw *zebra_pw_add(struct zebra_vrf *zvrf, const char *ifname, +			      uint8_t protocol, struct zserv *client) +{ +	struct zebra_pw *pw; + +	if (IS_ZEBRA_DEBUG_PW) +		zlog_debug("%u: adding pseudowire %s protocol %s", +			   zvrf_id(zvrf), ifname, zebra_route_string(protocol)); + +	pw = XCALLOC(MTYPE_PW, sizeof(*pw)); +	strlcpy(pw->ifname, ifname, sizeof(pw->ifname)); +	pw->protocol = protocol; +	pw->vrf_id = zvrf_id(zvrf); +	pw->client = client; +	pw->status = PW_STATUS_UP; + +	RB_INSERT(zebra_pw_head, &zvrf->pseudowires, pw); + +	return pw; +} + +void zebra_pw_del(struct zebra_vrf *zvrf, struct zebra_pw *pw) +{ +	if (IS_ZEBRA_DEBUG_PW) +		zlog_debug("%u: deleting pseudowire %s protocol %s", pw->vrf_id, +			   pw->ifname, zebra_route_string(pw->protocol)); + +	/* uninstall */ +	if (pw->status == PW_STATUS_UP) +		hook_call(pw_uninstall, pw); +	else if (pw->install_retry_timer) +		THREAD_TIMER_OFF(pw->install_retry_timer); + +	/* unlink and release memory */ +	RB_REMOVE(zebra_pw_head, &zvrf->pseudowires, pw); +	XFREE(MTYPE_PW, pw); +} + +void zebra_pw_change(struct zebra_pw *pw, ifindex_t ifindex, int type, int af, +		     union g_addr *nexthop, uint32_t local_label, +		     uint32_t remote_label, uint8_t flags, +		     union pw_protocol_fields *data) +{ +	pw->ifindex = ifindex; +	pw->type = type; +	pw->af = af; +	pw->nexthop = *nexthop; +	pw->local_label = local_label; +	pw->remote_label = remote_label; +	pw->flags = flags; +	pw->data = *data; + +	if (pw->enabled) +		zebra_pw_update(pw); +	else +		zebra_pw_uninstall(pw); +} + +struct zebra_pw *zebra_pw_find(struct zebra_vrf *zvrf, const char *ifname) +{ +	struct zebra_pw pw; +	strlcpy(pw.ifname, ifname, sizeof(pw.ifname)); +	return (RB_FIND(zebra_pw_head, &zvrf->pseudowires, &pw)); +} + +void zebra_pw_update(struct zebra_pw *pw) +{ +	if (zebra_pw_check_reachability(pw) < 0) { +		zebra_pw_uninstall(pw); +	} else { +		/* +		 * Install or reinstall the pseudowire (e.g. to update +		 * parameters like the nexthop or the use of the control word). +		 */ +		zebra_pw_install(pw); +	} +} + +static void zebra_pw_install(struct zebra_pw *pw) +{ +	if (IS_ZEBRA_DEBUG_PW) +		zlog_debug("%u: installing pseudowire %s protocol %s", +			   pw->vrf_id, pw->ifname, +			   zebra_route_string(pw->protocol)); + +	if (hook_call(pw_install, pw)) { +		zebra_pw_install_failure(pw); +		return; +	} + +	if (pw->status == PW_STATUS_DOWN) +		zebra_pw_update_status(pw, PW_STATUS_UP); +} + +static void zebra_pw_uninstall(struct zebra_pw *pw) +{ +	if (pw->status == PW_STATUS_DOWN) +		return; + +	if (IS_ZEBRA_DEBUG_PW) +		zlog_debug("%u: uninstalling pseudowire %s protocol %s", +			   pw->vrf_id, pw->ifname, +			   zebra_route_string(pw->protocol)); + +	/* ignore any possible error */ +	hook_call(pw_uninstall, pw); + +	if (pw->enabled) +		zebra_pw_update_status(pw, PW_STATUS_DOWN); +} + +/* + * Installation of the pseudowire in the kernel or hardware has failed. This + * function will notify the pseudowire client about the failure and schedule + * to retry the installation later. This function can be called by an external + * agent that performs the pseudowire installation in an asynchronous way. + */ +void zebra_pw_install_failure(struct zebra_pw *pw) +{ +	if (IS_ZEBRA_DEBUG_PW) +		zlog_debug( +			"%u: failed installing pseudowire %s, " +			"scheduling retry in %u seconds", +			pw->vrf_id, pw->ifname, PW_INSTALL_RETRY_INTERVAL); + +	/* schedule to retry later */ +	THREAD_TIMER_OFF(pw->install_retry_timer); +	pw->install_retry_timer = +		thread_add_timer(zebrad.master, zebra_pw_install_retry, pw, +				 PW_INSTALL_RETRY_INTERVAL); + +	zebra_pw_update_status(pw, PW_STATUS_DOWN); +} + +static int zebra_pw_install_retry(struct thread *thread) +{ +	struct zebra_pw *pw = THREAD_ARG(thread); + +	pw->install_retry_timer = NULL; +	zebra_pw_install(pw); + +	return 0; +} + +static void zebra_pw_update_status(struct zebra_pw *pw, int status) +{ +	pw->status = status; +	if (pw->client) +		zsend_pw_update(pw->client, pw); +} + +static int zebra_pw_check_reachability(struct zebra_pw *pw) +{ +	struct rib *rib; +	struct nexthop *nexthop, *tnexthop; +	int recursing; + +	/* TODO: consider GRE/L2TPv3 tunnels in addition to MPLS LSPs */ + +	/* find route to the remote end of the pseudowire */ +	rib = rib_match(family2afi(pw->af), SAFI_UNICAST, pw->vrf_id, +			&pw->nexthop, NULL); +	if (!rib) { +		if (IS_ZEBRA_DEBUG_PW) +			zlog_warn("%s: no route found for %s", __func__, +				  pw->ifname); +		return -1; +	} + +	/* +	 * Need to ensure that there's a label binding for all nexthops. +	 * Otherwise, ECMP for this route could render the pseudowire unusable. +	 */ +	for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing)) { +		if (!nexthop->nh_label) { +			if (IS_ZEBRA_DEBUG_PW) +				zlog_warn("%s: unlabeled route for %s", +					  __func__, pw->ifname); +			return -1; +		} +	} + +	return 0; +} + +void zebra_pw_client_close(struct zserv *client) +{ +	struct vrf *vrf; +	struct zebra_vrf *zvrf; +	struct zebra_pw *pw, *tmp; + +	RB_FOREACH(vrf, vrf_id_head, &vrfs_by_id) +	{ +		zvrf = vrf->info; +		RB_FOREACH_SAFE(pw, zebra_pw_head, &zvrf->pseudowires, tmp) +		{ +			if (pw->client != client) +				continue; +			zebra_pw_del(zvrf, pw); +		} +	} +} + +void zebra_pw_init(struct zebra_vrf *zvrf) +{ +	RB_INIT(&zvrf->pseudowires); +} + +void zebra_pw_exit(struct zebra_vrf *zvrf) +{ +	struct zebra_pw *pw; + +	while ((pw = RB_ROOT(&zvrf->pseudowires)) != NULL) +		zebra_pw_del(zvrf, pw); +} diff --git a/zebra/zebra_pw.h b/zebra/zebra_pw.h new file mode 100644 index 0000000000..62f45db5cd --- /dev/null +++ b/zebra/zebra_pw.h @@ -0,0 +1,67 @@ +/* Zebra PW code + * Copyright (C) 2016 Volta Networks, Inc. + * + * 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 + */ + +#ifndef ZEBRA_PW_H_ +#define ZEBRA_PW_H_ + +#include <net/if.h> +#include <netinet/in.h> + +#include "hook.h" + +#define PW_INSTALL_RETRY_INTERVAL	30 + +struct zebra_pw { +	RB_ENTRY(zebra_pw) entry; +	vrf_id_t vrf_id; +	char ifname[IF_NAMESIZE]; +	ifindex_t ifindex; +	int type; +	int af; +	union g_addr nexthop; +	uint32_t local_label; +	uint32_t remote_label; +	uint8_t flags; +	union pw_protocol_fields data; +	int enabled; +	int status; +	uint8_t protocol; +	struct zserv *client; +	struct thread *install_retry_timer; +}; + +RB_HEAD(zebra_pw_head, zebra_pw); +RB_PROTOTYPE(zebra_pw_head, zebra_pw, entry, zebra_pw_compare); + +DECLARE_HOOK(pw_install, (struct zebra_pw * pw), (pw)) +DECLARE_HOOK(pw_uninstall, (struct zebra_pw * pw), (pw)) + +struct zebra_pw *zebra_pw_add(struct zebra_vrf *, const char *, uint8_t, +			      struct zserv *); +void zebra_pw_del(struct zebra_vrf *, struct zebra_pw *); +void zebra_pw_change(struct zebra_pw *, ifindex_t, int, int, union g_addr *, +		     uint32_t, uint32_t, uint8_t, union pw_protocol_fields *); +struct zebra_pw *zebra_pw_find(struct zebra_vrf *, const char *); +void zebra_pw_update(struct zebra_pw *); +void zebra_pw_install_failure(struct zebra_pw *); +void zebra_pw_client_close(struct zserv *); +void zebra_pw_init(struct zebra_vrf *); +void zebra_pw_exit(struct zebra_vrf *); + +#endif /* ZEBRA_PW_H_ */ diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c index 87c1389b46..ff140bad67 100644 --- a/zebra/zebra_vrf.c +++ b/zebra/zebra_vrf.c @@ -203,6 +203,7 @@ static int zebra_vrf_delete(struct vrf *vrf)  		zebra_vxlan_close_tables(zvrf);  		zebra_mpls_close_tables(zvrf); +		zebra_pw_exit(zvrf);  		for (ALL_LIST_ELEMENTS_RO(vrf->iflist, node, ifp))  			if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(ifp); @@ -372,6 +373,7 @@ struct zebra_vrf *zebra_vrf_alloc(void)  	zebra_vxlan_init_tables(zvrf);  	zebra_mpls_init_tables(zvrf); +	zebra_pw_init(zvrf);  	return zvrf;  } diff --git a/zebra/zebra_vrf.h b/zebra/zebra_vrf.h index 3fdbe96dd4..a55c9d4598 100644 --- a/zebra/zebra_vrf.h +++ b/zebra/zebra_vrf.h @@ -23,6 +23,7 @@  #define __ZEBRA_RIB_H__  #include <zebra/zebra_ns.h> +#include <zebra/zebra_pw.h>  /* MPLS (Segment Routing) global block */  typedef struct mpls_srgb_t_ { @@ -89,6 +90,9 @@ struct zebra_vrf {  	/* MPLS Segment Routing Global block */  	mpls_srgb_t mpls_srgb; +	/* Pseudowires. */ +	struct zebra_pw_head pseudowires; +  	/* MPLS processing flags */  	u_int16_t mpls_flags;  #define MPLS_FLAG_SCHEDULE_LSPS    (1 << 0) diff --git a/zebra/zserv.c b/zebra/zserv.c index dae6785aee..bdb7755b63 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -1085,6 +1085,27 @@ int zsend_router_id_update(struct zserv *client, struct prefix *p,  	return zebra_server_send_message(client);  } +/* + * Function used by Zebra to send a PW status update to LDP daemon + */ +int zsend_pw_update(struct zserv *client, struct zebra_pw *pw) +{ +	struct stream *s; + +	s = client->obuf; +	stream_reset(s); + +	zserv_create_header(s, ZEBRA_PW_STATUS_UPDATE, pw->vrf_id); +	stream_write(s, pw->ifname, IF_NAMESIZE); +	stream_putl(s, pw->ifindex); +	stream_putl(s, pw->status); + +	/* Put length at the first point of the stream. */ +	stream_putw_at(s, 0, stream_get_endp(s)); + +	return zebra_server_send_message(client); +} +  /* Register zebra server interface information.  Send current all     interface and address information. */  static int zread_interface_add(struct zserv *client, u_short length, @@ -2037,6 +2058,97 @@ static void zread_label_manager_request(int cmd, struct zserv *client,  	}  } +static int zread_pseudowire(int command, struct zserv *client, u_short length, +			    vrf_id_t vrf_id) +{ +	struct stream *s; +	struct zebra_vrf *zvrf; +	char ifname[IF_NAMESIZE]; +	ifindex_t ifindex; +	int type; +	int af; +	union g_addr nexthop; +	uint32_t local_label; +	uint32_t remote_label; +	uint8_t flags; +	union pw_protocol_fields data; +	uint8_t protocol; +	struct zebra_pw *pw; + +	zvrf = vrf_info_lookup(vrf_id); +	if (!zvrf) +		return -1; + +	/* Get input stream.  */ +	s = client->ibuf; + +	/* Get data. */ +	stream_get(ifname, s, IF_NAMESIZE); +	ifindex = stream_getl(s); +	type = stream_getl(s); +	af = stream_getl(s); +	switch (af) { +	case AF_INET: +		nexthop.ipv4.s_addr = stream_get_ipv4(s); +		break; +	case AF_INET6: +		stream_get(&nexthop.ipv6, s, 16); +		break; +	default: +		return -1; +	} +	local_label = stream_getl(s); +	remote_label = stream_getl(s); +	flags = stream_getc(s); +	stream_get(&data, s, sizeof(data)); +	protocol = client->proto; + +	pw = zebra_pw_find(zvrf, ifname); +	switch (command) { +	case ZEBRA_PW_ADD: +		if (pw) { +			zlog_warn("%s: pseudowire %s already exists [%s]", +				  __func__, ifname, +				  zserv_command_string(command)); +			return -1; +		} + +		zebra_pw_add(zvrf, ifname, protocol, client); +		break; +	case ZEBRA_PW_DELETE: +		if (!pw) { +			zlog_warn("%s: pseudowire %s not found [%s]", __func__, +				  ifname, zserv_command_string(command)); +			return -1; +		} + +		zebra_pw_del(zvrf, pw); +		break; +	case ZEBRA_PW_SET: +	case ZEBRA_PW_UNSET: +		if (!pw) { +			zlog_warn("%s: pseudowire %s not found [%s]", __func__, +				  ifname, zserv_command_string(command)); +			return -1; +		} + +		switch (command) { +		case ZEBRA_PW_SET: +			pw->enabled = 1; +			break; +		case ZEBRA_PW_UNSET: +			pw->enabled = 0; +			break; +		} + +		zebra_pw_change(pw, ifindex, type, af, &nexthop, local_label, +				remote_label, flags, &data); +		break; +	} + +	return 0; +} +  /* Cleanup registered nexthops (across VRFs) upon client disconnect. */  static void zebra_client_close_cleanup_rnh(struct zserv *client)  { @@ -2081,6 +2193,9 @@ static void zebra_client_close(struct zserv *client)  	zebra_mpls_cleanup_fecs_for_client(vrf_info_lookup(VRF_DEFAULT),  					   client); +	/* Remove pseudowires associated with this client */ +	zebra_pw_client_close(client); +  	/* Close file descriptor. */  	if (client->sock) {  		unsigned long nroutes; @@ -2434,6 +2549,12 @@ static int zebra_client_read(struct thread *thread)  	case ZEBRA_INTERFACE_SET_MASTER:  		zread_interface_set_master(client, sock, length);  		break; +	case ZEBRA_PW_ADD: +	case ZEBRA_PW_DELETE: +	case ZEBRA_PW_SET: +	case ZEBRA_PW_UNSET: +		zread_pseudowire(command, client, length, vrf_id); +		break;  	default:  		zlog_info("Zebra received unknown command %d", command);  		break; diff --git a/zebra/zserv.h b/zebra/zserv.h index a2cf5d9f41..f661572d53 100644 --- a/zebra/zserv.h +++ b/zebra/zserv.h @@ -30,6 +30,8 @@  #include "zclient.h"  #include "zebra/zebra_ns.h" +#include "zebra/zebra_pw.h" +  /* Default port information. */  #define ZEBRA_VTY_PORT                2601 @@ -175,6 +177,7 @@ extern int zsend_interface_vrf_update(struct zserv *, struct interface *,  				      vrf_id_t);  extern int zsend_interface_link_params(struct zserv *, struct interface *); +extern int zsend_pw_update(struct zserv *, struct zebra_pw *);  extern pid_t pid;  | 
