mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-08 11:18:43 +00:00
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>
This commit is contained in:
parent
2f9c59f031
commit
6833ae01bc
@ -285,9 +285,6 @@ struct address_list_tlv {
|
|||||||
#define MAP_TYPE_GENPWID 0x81
|
#define MAP_TYPE_GENPWID 0x81
|
||||||
|
|
||||||
#define CONTROL_WORD_FLAG 0x8000
|
#define CONTROL_WORD_FLAG 0x8000
|
||||||
#define PW_TYPE_ETHERNET_TAGGED 0x0004
|
|
||||||
#define PW_TYPE_ETHERNET 0x0005
|
|
||||||
#define PW_TYPE_WILDCARD 0x7FFF
|
|
||||||
#define DEFAULT_PW_TYPE PW_TYPE_ETHERNET
|
#define DEFAULT_PW_TYPE PW_TYPE_ETHERNET
|
||||||
|
|
||||||
#define PW_TWCARD_RESERVED_BIT 0x8000
|
#define PW_TWCARD_RESERVED_BIT 0x8000
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include "prefix.h"
|
#include "prefix.h"
|
||||||
#include "filter.h"
|
#include "filter.h"
|
||||||
#include "vty.h"
|
#include "vty.h"
|
||||||
|
#include "pw.h"
|
||||||
|
|
||||||
#include "ldp.h"
|
#include "ldp.h"
|
||||||
|
|
||||||
|
@ -916,6 +916,11 @@ static const struct zebra_desc_table command_types[] = {
|
|||||||
DESC_ENTRY(ZEBRA_MACIP_DEL),
|
DESC_ENTRY(ZEBRA_MACIP_DEL),
|
||||||
DESC_ENTRY(ZEBRA_REMOTE_MACIP_ADD),
|
DESC_ENTRY(ZEBRA_REMOTE_MACIP_ADD),
|
||||||
DESC_ENTRY(ZEBRA_REMOTE_MACIP_DEL),
|
DESC_ENTRY(ZEBRA_REMOTE_MACIP_DEL),
|
||||||
|
DESC_ENTRY(ZEBRA_PW_ADD),
|
||||||
|
DESC_ENTRY(ZEBRA_PW_DELETE),
|
||||||
|
DESC_ENTRY(ZEBRA_PW_SET),
|
||||||
|
DESC_ENTRY(ZEBRA_PW_UNSET),
|
||||||
|
DESC_ENTRY(ZEBRA_PW_STATUS_UPDATE),
|
||||||
};
|
};
|
||||||
#undef DESC_ENTRY
|
#undef DESC_ENTRY
|
||||||
|
|
||||||
|
47
lib/pw.h
Normal file
47
lib/pw.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/* Pseudowire definitions
|
||||||
|
* 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 _FRR_PW_H
|
||||||
|
#define _FRR_PW_H
|
||||||
|
|
||||||
|
/* Pseudowire type - LDP and BGP use the same values. */
|
||||||
|
#define PW_TYPE_ETHERNET_TAGGED 0x0004 /* RFC 4446 */
|
||||||
|
#define PW_TYPE_ETHERNET 0x0005 /* RFC 4446 */
|
||||||
|
#define PW_TYPE_WILDCARD 0x7FFF /* RFC 4863, RFC 6668 */
|
||||||
|
|
||||||
|
/* Pseudowire flags. */
|
||||||
|
#define F_PSEUDOWIRE_CWORD 0x01
|
||||||
|
|
||||||
|
/* Pseudowire status. */
|
||||||
|
#define PW_STATUS_DOWN 0
|
||||||
|
#define PW_STATUS_UP 1
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Protocol-specific information about the pseudowire.
|
||||||
|
*/
|
||||||
|
union pw_protocol_fields {
|
||||||
|
struct {
|
||||||
|
/* TODO */
|
||||||
|
} ldp;
|
||||||
|
struct {
|
||||||
|
/* TODO */
|
||||||
|
} bgp;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _FRR_PW_H */
|
@ -123,6 +123,7 @@ pkginclude_HEADERS += \
|
|||||||
lib/prefix.h \
|
lib/prefix.h \
|
||||||
lib/privs.h \
|
lib/privs.h \
|
||||||
lib/ptm_lib.h \
|
lib/ptm_lib.h \
|
||||||
|
lib/pw.h \
|
||||||
lib/qobj.h \
|
lib/qobj.h \
|
||||||
lib/route_types.h \
|
lib/route_types.h \
|
||||||
lib/routemap.h \
|
lib/routemap.h \
|
||||||
|
@ -1834,6 +1834,69 @@ int lm_release_label_chunk(struct zclient *zclient, uint32_t start,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int zebra_send_pw(struct zclient *zclient, int command, struct zapi_pw *pw)
|
||||||
|
{
|
||||||
|
struct stream *s;
|
||||||
|
|
||||||
|
/* Reset stream. */
|
||||||
|
s = zclient->obuf;
|
||||||
|
stream_reset(s);
|
||||||
|
|
||||||
|
zclient_create_header(s, command, VRF_DEFAULT);
|
||||||
|
stream_write(s, pw->ifname, IF_NAMESIZE);
|
||||||
|
stream_putl(s, pw->ifindex);
|
||||||
|
|
||||||
|
/* Put type */
|
||||||
|
stream_putl(s, pw->type);
|
||||||
|
|
||||||
|
/* Put nexthop */
|
||||||
|
stream_putl(s, pw->af);
|
||||||
|
switch (pw->af) {
|
||||||
|
case AF_INET:
|
||||||
|
stream_put_in_addr(s, &pw->nexthop.ipv4);
|
||||||
|
break;
|
||||||
|
case AF_INET6:
|
||||||
|
stream_write(s, (u_char *)&pw->nexthop.ipv6, 16);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
zlog_err("%s: unknown af", __func__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Put labels */
|
||||||
|
stream_putl(s, pw->local_label);
|
||||||
|
stream_putl(s, pw->remote_label);
|
||||||
|
|
||||||
|
/* Put flags */
|
||||||
|
stream_putc(s, pw->flags);
|
||||||
|
|
||||||
|
/* Protocol specific fields */
|
||||||
|
stream_write(s, &pw->data, sizeof(union pw_protocol_fields));
|
||||||
|
|
||||||
|
/* Put length at the first point of the stream. */
|
||||||
|
stream_putw_at(s, 0, stream_get_endp(s));
|
||||||
|
|
||||||
|
return zclient_send_message(zclient);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Receive PW status update from Zebra and send it to LDE process.
|
||||||
|
*/
|
||||||
|
void zebra_read_pw_status_update(int command, struct zclient *zclient,
|
||||||
|
zebra_size_t length, vrf_id_t vrf_id,
|
||||||
|
struct zapi_pw_status *pw)
|
||||||
|
{
|
||||||
|
struct stream *s;
|
||||||
|
|
||||||
|
memset(pw, 0, sizeof(struct zapi_pw_status));
|
||||||
|
s = zclient->ibuf;
|
||||||
|
|
||||||
|
/* Get data. */
|
||||||
|
stream_get(pw->ifname, s, IF_NAMESIZE);
|
||||||
|
pw->ifindex = stream_getl(s);
|
||||||
|
pw->status = stream_getl(s);
|
||||||
|
}
|
||||||
|
|
||||||
/* Zebra client message read function. */
|
/* Zebra client message read function. */
|
||||||
static int zclient_read(struct thread *thread)
|
static int zclient_read(struct thread *thread)
|
||||||
{
|
{
|
||||||
@ -2061,6 +2124,11 @@ static int zclient_read(struct thread *thread)
|
|||||||
(*zclient->local_macip_del)(command, zclient, length,
|
(*zclient->local_macip_del)(command, zclient, length,
|
||||||
vrf_id);
|
vrf_id);
|
||||||
break;
|
break;
|
||||||
|
case ZEBRA_PW_STATUS_UPDATE:
|
||||||
|
if (zclient->pw_status_update)
|
||||||
|
(*zclient->pw_status_update)(command, zclient, length,
|
||||||
|
vrf_id);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,12 @@
|
|||||||
/* For vrf_bitmap_t. */
|
/* For vrf_bitmap_t. */
|
||||||
#include "vrf.h"
|
#include "vrf.h"
|
||||||
|
|
||||||
|
/* For union g_addr */
|
||||||
|
#include "nexthop.h"
|
||||||
|
|
||||||
|
/* For union pw_protocol_fields */
|
||||||
|
#include "pw.h"
|
||||||
|
|
||||||
/* For input/output buffer to zebra. */
|
/* For input/output buffer to zebra. */
|
||||||
#define ZEBRA_MAX_PACKET_SIZ 4096
|
#define ZEBRA_MAX_PACKET_SIZ 4096
|
||||||
|
|
||||||
@ -106,6 +112,11 @@ typedef enum {
|
|||||||
ZEBRA_MACIP_DEL,
|
ZEBRA_MACIP_DEL,
|
||||||
ZEBRA_REMOTE_MACIP_ADD,
|
ZEBRA_REMOTE_MACIP_ADD,
|
||||||
ZEBRA_REMOTE_MACIP_DEL,
|
ZEBRA_REMOTE_MACIP_DEL,
|
||||||
|
ZEBRA_PW_ADD,
|
||||||
|
ZEBRA_PW_DELETE,
|
||||||
|
ZEBRA_PW_SET,
|
||||||
|
ZEBRA_PW_UNSET,
|
||||||
|
ZEBRA_PW_STATUS_UPDATE,
|
||||||
} zebra_message_types_t;
|
} zebra_message_types_t;
|
||||||
|
|
||||||
struct redist_proto {
|
struct redist_proto {
|
||||||
@ -187,6 +198,7 @@ struct zclient {
|
|||||||
int (*local_vni_del)(int, struct zclient *, uint16_t, vrf_id_t);
|
int (*local_vni_del)(int, struct zclient *, uint16_t, vrf_id_t);
|
||||||
int (*local_macip_add)(int, struct zclient *, uint16_t, vrf_id_t);
|
int (*local_macip_add)(int, struct zclient *, uint16_t, vrf_id_t);
|
||||||
int (*local_macip_del)(int, struct zclient *, uint16_t, vrf_id_t);
|
int (*local_macip_del)(int, struct zclient *, uint16_t, vrf_id_t);
|
||||||
|
int (*pw_status_update)(int, struct zclient *, uint16_t, vrf_id_t);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Zebra API message flag. */
|
/* Zebra API message flag. */
|
||||||
@ -266,6 +278,25 @@ struct zapi_ipv4 {
|
|||||||
vrf_id_t vrf_id;
|
vrf_id_t vrf_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct zapi_pw {
|
||||||
|
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 zapi_pw_status {
|
||||||
|
char ifname[IF_NAMESIZE];
|
||||||
|
ifindex_t ifindex;
|
||||||
|
uint32_t status;
|
||||||
|
};
|
||||||
|
|
||||||
/* Prototypes of zebra client service functions. */
|
/* Prototypes of zebra client service functions. */
|
||||||
extern struct zclient *zclient_new(struct thread_master *);
|
extern struct zclient *zclient_new(struct thread_master *);
|
||||||
extern void zclient_init(struct zclient *, int, u_short);
|
extern void zclient_init(struct zclient *, int, u_short);
|
||||||
@ -338,6 +369,12 @@ extern int lm_get_label_chunk(struct zclient *zclient, u_char keep,
|
|||||||
uint32_t *end);
|
uint32_t *end);
|
||||||
extern int lm_release_label_chunk(struct zclient *zclient, uint32_t start,
|
extern int lm_release_label_chunk(struct zclient *zclient, uint32_t start,
|
||||||
uint32_t end);
|
uint32_t end);
|
||||||
|
extern int zebra_send_pw(struct zclient *zclient, int command,
|
||||||
|
struct zapi_pw *pw);
|
||||||
|
extern void zebra_read_pw_status_update(int command, struct zclient *zclient,
|
||||||
|
zebra_size_t length, vrf_id_t vrf_id,
|
||||||
|
struct zapi_pw_status *pw);
|
||||||
|
|
||||||
/* IPv6 prefix add and delete function prototype. */
|
/* IPv6 prefix add and delete function prototype. */
|
||||||
|
|
||||||
struct zapi_ipv6 {
|
struct zapi_ipv6 {
|
||||||
|
@ -32,6 +32,7 @@ unsigned long zebra_debug_fpm;
|
|||||||
unsigned long zebra_debug_nht;
|
unsigned long zebra_debug_nht;
|
||||||
unsigned long zebra_debug_mpls;
|
unsigned long zebra_debug_mpls;
|
||||||
unsigned long zebra_debug_vxlan;
|
unsigned long zebra_debug_vxlan;
|
||||||
|
unsigned long zebra_debug_pw;
|
||||||
|
|
||||||
DEFUN (show_debugging_zebra,
|
DEFUN (show_debugging_zebra,
|
||||||
show_debugging_zebra_cmd,
|
show_debugging_zebra_cmd,
|
||||||
@ -82,6 +83,8 @@ DEFUN (show_debugging_zebra,
|
|||||||
vty_out(vty, " Zebra next-hop tracking debugging is on\n");
|
vty_out(vty, " Zebra next-hop tracking debugging is on\n");
|
||||||
if (IS_ZEBRA_DEBUG_MPLS)
|
if (IS_ZEBRA_DEBUG_MPLS)
|
||||||
vty_out(vty, " Zebra MPLS debugging is on\n");
|
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;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -130,6 +133,21 @@ DEFUN (debug_zebra_vxlan,
|
|||||||
return CMD_WARNING;
|
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,
|
DEFUN (debug_zebra_packet,
|
||||||
debug_zebra_packet_cmd,
|
debug_zebra_packet_cmd,
|
||||||
"debug zebra packet [<recv|send>] [detail]",
|
"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");
|
vty_out(vty, "debug zebra vxlan\n");
|
||||||
write++;
|
write++;
|
||||||
}
|
}
|
||||||
|
if (IS_ZEBRA_DEBUG_PW) {
|
||||||
|
vty_out(vty, "debug zebra pseudowires%s", VTY_NEWLINE);
|
||||||
|
write++;
|
||||||
|
}
|
||||||
return write;
|
return write;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -431,6 +453,7 @@ void zebra_debug_init(void)
|
|||||||
zebra_debug_fpm = 0;
|
zebra_debug_fpm = 0;
|
||||||
zebra_debug_mpls = 0;
|
zebra_debug_mpls = 0;
|
||||||
zebra_debug_vxlan = 0;
|
zebra_debug_vxlan = 0;
|
||||||
|
zebra_debug_pw = 0;
|
||||||
|
|
||||||
install_node(&debug_node, config_write_debug);
|
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_nht_cmd);
|
||||||
install_element(ENABLE_NODE, &debug_zebra_mpls_cmd);
|
install_element(ENABLE_NODE, &debug_zebra_mpls_cmd);
|
||||||
install_element(ENABLE_NODE, &debug_zebra_vxlan_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_packet_cmd);
|
||||||
install_element(ENABLE_NODE, &debug_zebra_kernel_cmd);
|
install_element(ENABLE_NODE, &debug_zebra_kernel_cmd);
|
||||||
install_element(ENABLE_NODE, &debug_zebra_kernel_msgdump_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_nht_cmd);
|
||||||
install_element(CONFIG_NODE, &debug_zebra_mpls_cmd);
|
install_element(CONFIG_NODE, &debug_zebra_mpls_cmd);
|
||||||
install_element(CONFIG_NODE, &debug_zebra_vxlan_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_packet_cmd);
|
||||||
install_element(CONFIG_NODE, &debug_zebra_kernel_cmd);
|
install_element(CONFIG_NODE, &debug_zebra_kernel_cmd);
|
||||||
install_element(CONFIG_NODE, &debug_zebra_kernel_msgdump_cmd);
|
install_element(CONFIG_NODE, &debug_zebra_kernel_msgdump_cmd);
|
||||||
|
@ -44,6 +44,8 @@
|
|||||||
|
|
||||||
#define ZEBRA_DEBUG_VXLAN 0x01
|
#define ZEBRA_DEBUG_VXLAN 0x01
|
||||||
|
|
||||||
|
#define ZEBRA_DEBUG_PW 0x01
|
||||||
|
|
||||||
/* Debug related macro. */
|
/* Debug related macro. */
|
||||||
#define IS_ZEBRA_DEBUG_EVENT (zebra_debug_event & ZEBRA_DEBUG_EVENT)
|
#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_NHT (zebra_debug_nht & ZEBRA_DEBUG_NHT)
|
||||||
#define IS_ZEBRA_DEBUG_MPLS (zebra_debug_mpls & ZEBRA_DEBUG_MPLS)
|
#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_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_event;
|
||||||
extern unsigned long zebra_debug_packet;
|
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_nht;
|
||||||
extern unsigned long zebra_debug_mpls;
|
extern unsigned long zebra_debug_mpls;
|
||||||
extern unsigned long zebra_debug_vxlan;
|
extern unsigned long zebra_debug_vxlan;
|
||||||
|
extern unsigned long zebra_debug_pw;
|
||||||
|
|
||||||
extern void zebra_debug_init(void);
|
extern void zebra_debug_init(void);
|
||||||
|
|
||||||
|
@ -56,6 +56,7 @@ zebra_zebra_SOURCES = \
|
|||||||
zebra/zebra_ns.c \
|
zebra/zebra_ns.c \
|
||||||
zebra/zebra_ptm.c \
|
zebra/zebra_ptm.c \
|
||||||
zebra/zebra_ptm_redistribute.c \
|
zebra/zebra_ptm_redistribute.c \
|
||||||
|
zebra/zebra_pw.c \
|
||||||
zebra/zebra_rib.c \
|
zebra/zebra_rib.c \
|
||||||
zebra/zebra_rnh.c \
|
zebra/zebra_rnh.c \
|
||||||
zebra/zebra_routemap.c \
|
zebra/zebra_routemap.c \
|
||||||
@ -95,6 +96,7 @@ noinst_HEADERS += \
|
|||||||
zebra/zebra_ns.h \
|
zebra/zebra_ns.h \
|
||||||
zebra/zebra_ptm.h \
|
zebra/zebra_ptm.h \
|
||||||
zebra/zebra_ptm_redistribute.h \
|
zebra/zebra_ptm_redistribute.h \
|
||||||
|
zebra/zebra_pw.h \
|
||||||
zebra/zebra_rnh.h \
|
zebra/zebra_rnh.h \
|
||||||
zebra/zebra_routemap.h \
|
zebra/zebra_routemap.h \
|
||||||
zebra/zebra_static.h \
|
zebra/zebra_static.h \
|
||||||
|
268
zebra/zebra_pw.c
Normal file
268
zebra/zebra_pw.c
Normal file
@ -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);
|
||||||
|
}
|
67
zebra/zebra_pw.h
Normal file
67
zebra/zebra_pw.h
Normal file
@ -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_ */
|
@ -203,6 +203,7 @@ static int zebra_vrf_delete(struct vrf *vrf)
|
|||||||
zebra_vxlan_close_tables(zvrf);
|
zebra_vxlan_close_tables(zvrf);
|
||||||
|
|
||||||
zebra_mpls_close_tables(zvrf);
|
zebra_mpls_close_tables(zvrf);
|
||||||
|
zebra_pw_exit(zvrf);
|
||||||
|
|
||||||
for (ALL_LIST_ELEMENTS_RO(vrf->iflist, node, ifp))
|
for (ALL_LIST_ELEMENTS_RO(vrf->iflist, node, ifp))
|
||||||
if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(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_vxlan_init_tables(zvrf);
|
||||||
zebra_mpls_init_tables(zvrf);
|
zebra_mpls_init_tables(zvrf);
|
||||||
|
zebra_pw_init(zvrf);
|
||||||
|
|
||||||
return zvrf;
|
return zvrf;
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#define __ZEBRA_RIB_H__
|
#define __ZEBRA_RIB_H__
|
||||||
|
|
||||||
#include <zebra/zebra_ns.h>
|
#include <zebra/zebra_ns.h>
|
||||||
|
#include <zebra/zebra_pw.h>
|
||||||
|
|
||||||
/* MPLS (Segment Routing) global block */
|
/* MPLS (Segment Routing) global block */
|
||||||
typedef struct mpls_srgb_t_ {
|
typedef struct mpls_srgb_t_ {
|
||||||
@ -89,6 +90,9 @@ struct zebra_vrf {
|
|||||||
/* MPLS Segment Routing Global block */
|
/* MPLS Segment Routing Global block */
|
||||||
mpls_srgb_t mpls_srgb;
|
mpls_srgb_t mpls_srgb;
|
||||||
|
|
||||||
|
/* Pseudowires. */
|
||||||
|
struct zebra_pw_head pseudowires;
|
||||||
|
|
||||||
/* MPLS processing flags */
|
/* MPLS processing flags */
|
||||||
u_int16_t mpls_flags;
|
u_int16_t mpls_flags;
|
||||||
#define MPLS_FLAG_SCHEDULE_LSPS (1 << 0)
|
#define MPLS_FLAG_SCHEDULE_LSPS (1 << 0)
|
||||||
|
121
zebra/zserv.c
121
zebra/zserv.c
@ -1085,6 +1085,27 @@ int zsend_router_id_update(struct zserv *client, struct prefix *p,
|
|||||||
return zebra_server_send_message(client);
|
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
|
/* Register zebra server interface information. Send current all
|
||||||
interface and address information. */
|
interface and address information. */
|
||||||
static int zread_interface_add(struct zserv *client, u_short length,
|
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. */
|
/* Cleanup registered nexthops (across VRFs) upon client disconnect. */
|
||||||
static void zebra_client_close_cleanup_rnh(struct zserv *client)
|
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),
|
zebra_mpls_cleanup_fecs_for_client(vrf_info_lookup(VRF_DEFAULT),
|
||||||
client);
|
client);
|
||||||
|
|
||||||
|
/* Remove pseudowires associated with this client */
|
||||||
|
zebra_pw_client_close(client);
|
||||||
|
|
||||||
/* Close file descriptor. */
|
/* Close file descriptor. */
|
||||||
if (client->sock) {
|
if (client->sock) {
|
||||||
unsigned long nroutes;
|
unsigned long nroutes;
|
||||||
@ -2434,6 +2549,12 @@ static int zebra_client_read(struct thread *thread)
|
|||||||
case ZEBRA_INTERFACE_SET_MASTER:
|
case ZEBRA_INTERFACE_SET_MASTER:
|
||||||
zread_interface_set_master(client, sock, length);
|
zread_interface_set_master(client, sock, length);
|
||||||
break;
|
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:
|
default:
|
||||||
zlog_info("Zebra received unknown command %d", command);
|
zlog_info("Zebra received unknown command %d", command);
|
||||||
break;
|
break;
|
||||||
|
@ -30,6 +30,8 @@
|
|||||||
#include "zclient.h"
|
#include "zclient.h"
|
||||||
|
|
||||||
#include "zebra/zebra_ns.h"
|
#include "zebra/zebra_ns.h"
|
||||||
|
#include "zebra/zebra_pw.h"
|
||||||
|
|
||||||
/* Default port information. */
|
/* Default port information. */
|
||||||
#define ZEBRA_VTY_PORT 2601
|
#define ZEBRA_VTY_PORT 2601
|
||||||
|
|
||||||
@ -175,6 +177,7 @@ extern int zsend_interface_vrf_update(struct zserv *, struct interface *,
|
|||||||
vrf_id_t);
|
vrf_id_t);
|
||||||
|
|
||||||
extern int zsend_interface_link_params(struct zserv *, struct interface *);
|
extern int zsend_interface_link_params(struct zserv *, struct interface *);
|
||||||
|
extern int zsend_pw_update(struct zserv *, struct zebra_pw *);
|
||||||
|
|
||||||
extern pid_t pid;
|
extern pid_t pid;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user