diff options
author | Renato Westphal <renato@cvs.openbsd.org> | 2017-03-04 00:21:49 +0000 |
---|---|---|
committer | Renato Westphal <renato@cvs.openbsd.org> | 2017-03-04 00:21:49 +0000 |
commit | f143cfa624bd75447244d10a6363f04101dedcd0 (patch) | |
tree | dc0a5092bfa947fdad752516398a4aeb575004fd | |
parent | 94c1e73a6e871bdcf3d92af851ba3809ecdeb843 (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.c | 79 | ||||
-rw-r--r-- | usr.sbin/ldpd/kroute.c | 5 | ||||
-rw-r--r-- | usr.sbin/ldpd/l2vpn.c | 31 | ||||
-rw-r--r-- | usr.sbin/ldpd/lde.h | 3 | ||||
-rw-r--r-- | usr.sbin/ldpd/ldp.h | 3 | ||||
-rw-r--r-- | usr.sbin/ldpd/ldpd.h | 8 | ||||
-rw-r--r-- | usr.sbin/ldpd/ldpe.c | 26 | ||||
-rw-r--r-- | usr.sbin/ldpd/ldpe.h | 3 |
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 */ |