summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRenato Westphal <renato@cvs.openbsd.org>2017-03-04 00:21:49 +0000
committerRenato Westphal <renato@cvs.openbsd.org>2017-03-04 00:21:49 +0000
commitf143cfa624bd75447244d10a6363f04101dedcd0 (patch)
treedc0a5092bfa947fdad752516398a4aeb575004fd
parent94c1e73a6e871bdcf3d92af851ba3809ecdeb843 (diff)
Send VPLS MAC withdrawals.
RFC 4762 says that MAC address withdrawal messages can be used to improve convergence time in VPLS networks. This patch makes ldpd send MAC withdrawals whenever a non-pseudowire interface pertaining to a VPLS goes down. The processing of received MAC withdrawals will be implemented later.
-rw-r--r--usr.sbin/ldpd/address.c79
-rw-r--r--usr.sbin/ldpd/kroute.c5
-rw-r--r--usr.sbin/ldpd/l2vpn.c31
-rw-r--r--usr.sbin/ldpd/lde.h3
-rw-r--r--usr.sbin/ldpd/ldp.h3
-rw-r--r--usr.sbin/ldpd/ldpd.h8
-rw-r--r--usr.sbin/ldpd/ldpe.c26
-rw-r--r--usr.sbin/ldpd/ldpe.h3
8 files changed, 135 insertions, 23 deletions
diff --git a/usr.sbin/ldpd/address.c b/usr.sbin/ldpd/address.c
index 6d23e15ff2e..354797eb9aa 100644
--- a/usr.sbin/ldpd/address.c
+++ b/usr.sbin/ldpd/address.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: address.c,v 1.34 2017/03/04 00:18:43 renato Exp $ */
+/* $OpenBSD: address.c,v 1.35 2017/03/04 00:21:48 renato Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -28,12 +28,14 @@
static void send_address(struct nbr *, int, struct if_addr_head *,
unsigned int, int);
-static int gen_address_list_tlv(struct ibuf *, uint16_t, int,
- struct if_addr_head *, unsigned int);
+static int gen_address_list_tlv(struct ibuf *, int, struct if_addr_head *,
+ unsigned int);
+static int gen_mac_list_tlv(struct ibuf *, uint8_t *);
static void address_list_add(struct if_addr_head *, struct if_addr *);
static void address_list_clr(struct if_addr_head *);
static void log_msg_address(int, uint16_t, struct nbr *, int,
union ldpd_addr *);
+static void log_msg_mac_withdrawal(int, struct nbr *, uint8_t *);
static void
send_address(struct nbr *nbr, int af, struct if_addr_head *addr_list,
@@ -87,8 +89,7 @@ send_address(struct nbr *nbr, int af, struct if_addr_head *addr_list,
size -= LDP_HDR_SIZE;
err |= gen_msg_hdr(buf, msg_type, size);
size -= LDP_MSG_SIZE;
- err |= gen_address_list_tlv(buf, size, af, addr_list,
- tlv_addr_count);
+ err |= gen_address_list_tlv(buf, af, addr_list, tlv_addr_count);
if (err) {
address_list_clr(addr_list);
ibuf_free(buf);
@@ -139,6 +140,40 @@ send_address_all(struct nbr *nbr, int af)
send_address(nbr, af, &addr_list, addr_count, 0);
}
+void
+send_mac_withdrawal(struct nbr *nbr, struct map *fec, uint8_t *mac)
+{
+ struct ibuf *buf;
+ uint16_t size;
+ int err;
+
+ size = LDP_HDR_SIZE + LDP_MSG_SIZE + ADDR_LIST_SIZE + len_fec_tlv(fec) +
+ TLV_HDR_SIZE;
+ if (mac)
+ size += ETHER_ADDR_LEN;
+
+ if ((buf = ibuf_open(size)) == NULL)
+ fatal(__func__);
+
+ err = gen_ldp_hdr(buf, size);
+ size -= LDP_HDR_SIZE;
+ err |= gen_msg_hdr(buf, MSG_TYPE_ADDRWITHDRAW, size);
+ size -= LDP_MSG_SIZE;
+ err |= gen_address_list_tlv(buf, AF_INET, NULL, 0);
+ err |= gen_fec_tlv(buf, fec);
+ err |= gen_mac_list_tlv(buf, mac);
+ if (err) {
+ ibuf_free(buf);
+ return;
+ }
+
+ log_msg_mac_withdrawal(1, nbr, mac);
+
+ evbuf_enqueue(&nbr->tcp->wbuf, buf);
+
+ nbr_fsm(nbr, NBR_EVT_PDU_SENT);
+}
+
int
recv_address(struct nbr *nbr, char *buf, uint16_t len)
{
@@ -280,8 +315,8 @@ recv_address(struct nbr *nbr, char *buf, uint16_t len)
}
static int
-gen_address_list_tlv(struct ibuf *buf, uint16_t size, int af,
- struct if_addr_head *addr_list, unsigned int tlv_addr_count)
+gen_address_list_tlv(struct ibuf *buf, int af, struct if_addr_head *addr_list,
+ unsigned int tlv_addr_count)
{
struct address_list_tlv alt;
uint16_t addr_size;
@@ -290,7 +325,6 @@ gen_address_list_tlv(struct ibuf *buf, uint16_t size, int af,
memset(&alt, 0, sizeof(alt));
alt.type = htons(TLV_TYPE_ADDRLIST);
- alt.length = htons(size - TLV_HDR_SIZE);
switch (af) {
case AF_INET:
@@ -304,8 +338,12 @@ gen_address_list_tlv(struct ibuf *buf, uint16_t size, int af,
default:
fatalx("gen_address_list_tlv: unknown af");
}
+ alt.length = htons(sizeof(alt.family) + addr_size * tlv_addr_count);
err |= ibuf_add(buf, &alt, sizeof(alt));
+ if (addr_list == NULL)
+ return (err);
+
LIST_FOREACH(if_addr, addr_list, entry) {
err |= ibuf_add(buf, &if_addr->addr, addr_size);
if (--tlv_addr_count == 0)
@@ -315,6 +353,23 @@ gen_address_list_tlv(struct ibuf *buf, uint16_t size, int af,
return (err);
}
+static int
+gen_mac_list_tlv(struct ibuf *buf, uint8_t *mac)
+{
+ struct tlv tlv;
+ int err;
+
+ memset(&tlv, 0, sizeof(tlv));
+ tlv.type = htons(TLV_TYPE_MAC_LIST);
+ if (mac)
+ tlv.length = htons(ETHER_ADDR_LEN);
+ err = ibuf_add(buf, &tlv, sizeof(tlv));
+ if (mac)
+ err |= ibuf_add(buf, mac, ETHER_ADDR_LEN);
+
+ return (err);
+}
+
static void
address_list_add(struct if_addr_head *addr_list, struct if_addr *if_addr)
{
@@ -346,3 +401,11 @@ log_msg_address(int out, uint16_t msg_type, struct nbr *nbr, int af,
log_debug("msg-%s: %s: lsr-id %s, address %s", (out) ? "out" : "in",
msg_name(msg_type), inet_ntoa(nbr->id), log_addr(af, addr));
}
+
+static void
+log_msg_mac_withdrawal(int out, struct nbr *nbr, uint8_t *mac)
+{
+ log_debug("msg-%s: mac withdrawal: lsr-id %s, mac %s",
+ (out) ? "out" : "in", inet_ntoa(nbr->id),
+ (mac) ? ether_ntoa((struct ether_addr *)mac) : "wildcard");
+}
diff --git a/usr.sbin/ldpd/kroute.c b/usr.sbin/ldpd/kroute.c
index 6a2f921f773..7e20c40f5c1 100644
--- a/usr.sbin/ldpd/kroute.c
+++ b/usr.sbin/ldpd/kroute.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kroute.c,v 1.64 2017/03/03 23:41:27 renato Exp $ */
+/* $OpenBSD: kroute.c,v 1.65 2017/03/04 00:21:48 renato Exp $ */
/*
* Copyright (c) 2015, 2016 Renato Westphal <renato@openbsd.org>
@@ -25,6 +25,7 @@
#include <sys/sysctl.h>
#include <arpa/inet.h>
#include <net/if_dl.h>
+#include <net/if_types.h>
#include <net/route.h>
#include <netmpls/mpls.h>
#include <errno.h>
@@ -873,6 +874,8 @@ kif_update(unsigned short ifindex, int flags, struct if_data *ifd,
kif->k.flags = flags;
kif->k.link_state = ifd->ifi_link_state;
+ if (sdl)
+ memcpy(kif->k.mac, LLADDR(sdl), sizeof(kif->k.mac));
kif->k.if_type = ifd->ifi_type;
kif->k.baudrate = ifd->ifi_baudrate;
kif->k.mtu = ifd->ifi_mtu;
diff --git a/usr.sbin/ldpd/l2vpn.c b/usr.sbin/ldpd/l2vpn.c
index f963c9ad8ad..197156d5a2e 100644
--- a/usr.sbin/ldpd/l2vpn.c
+++ b/usr.sbin/ldpd/l2vpn.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: l2vpn.c,v 1.23 2017/03/04 00:12:25 renato Exp $ */
+/* $OpenBSD: l2vpn.c,v 1.24 2017/03/04 00:21:48 renato Exp $ */
/*
* Copyright (c) 2015 Renato Westphal <renato@openbsd.org>
@@ -111,7 +111,7 @@ l2vpn_if_new(struct l2vpn *l2vpn, struct kif *kif)
strlcpy(lif->ifname, kif->ifname, sizeof(lif->ifname));
lif->ifindex = kif->ifindex;
lif->flags = kif->flags;
- lif->link_state = kif->link_state;
+ lif->linkstate = kif->link_state;
return (lif);
}
@@ -128,6 +128,33 @@ l2vpn_if_find(struct l2vpn *l2vpn, unsigned int ifindex)
return (NULL);
}
+void
+l2vpn_if_update(struct l2vpn_if *lif)
+{
+ struct l2vpn *l2vpn = lif->l2vpn;
+ struct l2vpn_pw *pw;
+ struct map fec;
+ struct nbr *nbr;
+
+ if ((lif->flags & IFF_UP) && LINK_STATE_IS_UP(lif->linkstate))
+ return;
+
+ LIST_FOREACH(pw, &l2vpn->pw_list, entry) {
+ nbr = nbr_find_ldpid(pw->lsr_id.s_addr);
+ if (nbr == NULL)
+ continue;
+
+ memset(&fec, 0, sizeof(fec));
+ fec.type = MAP_TYPE_PWID;
+ fec.fec.pwid.type = l2vpn->pw_type;
+ fec.fec.pwid.group_id = 0;
+ fec.flags |= F_MAP_PW_ID;
+ fec.fec.pwid.pwid = pw->pwid;
+
+ send_mac_withdrawal(nbr, &fec, lif->mac);
+ }
+}
+
struct l2vpn_pw *
l2vpn_pw_new(struct l2vpn *l2vpn, struct kif *kif)
{
diff --git a/usr.sbin/ldpd/lde.h b/usr.sbin/ldpd/lde.h
index ec76293560f..d83a3d3ad6a 100644
--- a/usr.sbin/ldpd/lde.h
+++ b/usr.sbin/ldpd/lde.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: lde.h,v 1.49 2017/03/04 00:15:35 renato Exp $ */
+/* $OpenBSD: lde.h,v 1.50 2017/03/04 00:21:48 renato Exp $ */
/*
* Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org>
@@ -198,6 +198,7 @@ void l2vpn_init(struct l2vpn *);
void l2vpn_exit(struct l2vpn *);
struct l2vpn_if *l2vpn_if_new(struct l2vpn *, struct kif *);
struct l2vpn_if *l2vpn_if_find(struct l2vpn *, unsigned int);
+void l2vpn_if_update(struct l2vpn_if *);
struct l2vpn_pw *l2vpn_pw_new(struct l2vpn *, struct kif *);
struct l2vpn_pw *l2vpn_pw_find(struct l2vpn *, unsigned int);
void l2vpn_pw_init(struct l2vpn_pw *);
diff --git a/usr.sbin/ldpd/ldp.h b/usr.sbin/ldpd/ldp.h
index ef6374c7f9a..273e0832761 100644
--- a/usr.sbin/ldpd/ldp.h
+++ b/usr.sbin/ldpd/ldp.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldp.h,v 1.41 2017/03/04 00:15:35 renato Exp $ */
+/* $OpenBSD: ldp.h,v 1.42 2017/03/04 00:21:48 renato Exp $ */
/*
* Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org>
@@ -95,6 +95,7 @@
#define TLV_TYPE_FRSESSION 0x0502
#define TLV_TYPE_LABELREQUEST 0x0600
/* RFC 4447 */
+#define TLV_TYPE_MAC_LIST 0x8404
#define TLV_TYPE_PW_STATUS 0x896A
#define TLV_TYPE_PW_IF_PARAM 0x096B
#define TLV_TYPE_PW_GROUP_ID 0x096C
diff --git a/usr.sbin/ldpd/ldpd.h b/usr.sbin/ldpd/ldpd.h
index 6596e5467a9..576d340e200 100644
--- a/usr.sbin/ldpd/ldpd.h
+++ b/usr.sbin/ldpd/ldpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldpd.h,v 1.86 2017/03/04 00:12:26 renato Exp $ */
+/* $OpenBSD: ldpd.h,v 1.87 2017/03/04 00:21:48 renato Exp $ */
/*
* Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org>
@@ -26,8 +26,10 @@
#include <sys/socket.h>
#include <sys/queue.h>
#include <sys/tree.h>
+#include <net/if_arp.h>
#include <net/if.h>
#include <netinet/in.h>
+#include <netinet/if_ether.h>
#include <event.h>
#include <imsg.h>
@@ -327,7 +329,8 @@ struct l2vpn_if {
char ifname[IF_NAMESIZE];
unsigned int ifindex;
uint16_t flags;
- uint8_t link_state;
+ uint8_t linkstate;
+ uint8_t mac[ETHER_ADDR_LEN];
};
struct l2vpn_pw {
@@ -474,6 +477,7 @@ struct kif {
unsigned short ifindex;
int flags;
uint8_t link_state;
+ uint8_t mac[ETHER_ADDR_LEN];
int mtu;
unsigned int rdomain;
uint8_t if_type;
diff --git a/usr.sbin/ldpd/ldpe.c b/usr.sbin/ldpd/ldpe.c
index 5de42b5b8e1..b30ab0f3c96 100644
--- a/usr.sbin/ldpd/ldpe.c
+++ b/usr.sbin/ldpd/ldpe.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldpe.c,v 1.73 2017/03/03 23:41:27 renato Exp $ */
+/* $OpenBSD: ldpe.c,v 1.74 2017/03/04 00:21:48 renato Exp $ */
/*
* Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org>
@@ -221,8 +221,8 @@ ldpe_dispatch_main(int fd, short event, void *bula)
struct iface *niface;
struct tnbr *ntnbr;
struct nbr_params *nnbrp;
- static struct l2vpn *nl2vpn;
- struct l2vpn_if *nlif;
+ static struct l2vpn *l2vpn, *nl2vpn;
+ struct l2vpn_if *lif = NULL, *nlif;
struct l2vpn_pw *npw;
struct imsg imsg;
struct imsgev *iev = bula;
@@ -265,12 +265,24 @@ ldpe_dispatch_main(int fd, short event, void *bula)
kif = imsg.data;
iface = if_lookup(leconf, kif->ifindex);
- if (!iface)
+ if (iface) {
+ iface->flags = kif->flags;
+ iface->linkstate = kif->link_state;
+ if_update(iface, AF_UNSPEC);
break;
+ }
- iface->flags = kif->flags;
- iface->linkstate = kif->link_state;
- if_update(iface, AF_UNSPEC);
+ LIST_FOREACH(l2vpn, &leconf->l2vpn_list, entry) {
+ lif = l2vpn_if_find(l2vpn, kif->ifindex);
+ if (lif) {
+ lif->flags = kif->flags;
+ lif->linkstate = kif->link_state;
+ memcpy(lif->mac, kif->mac,
+ sizeof(lif->mac));
+ l2vpn_if_update(lif);
+ break;
+ }
+ }
break;
case IMSG_NEWADDR:
if (imsg.hdr.len != IMSG_HEADER_SIZE +
diff --git a/usr.sbin/ldpd/ldpe.h b/usr.sbin/ldpd/ldpe.h
index cc9882d6c22..569e8ffc8bc 100644
--- a/usr.sbin/ldpd/ldpe.h
+++ b/usr.sbin/ldpd/ldpe.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldpe.h,v 1.74 2017/03/04 00:15:35 renato Exp $ */
+/* $OpenBSD: ldpe.h,v 1.75 2017/03/04 00:21:48 renato Exp $ */
/*
* Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org>
@@ -173,6 +173,7 @@ int gen_status_tlv(struct ibuf *, uint32_t, uint32_t, uint16_t);
/* address.c */
void send_address_single(struct nbr *, struct if_addr *, int);
void send_address_all(struct nbr *, int);
+void send_mac_withdrawal(struct nbr *, struct map *, uint8_t *);
int recv_address(struct nbr *, char *, uint16_t);
/* labelmapping.c */