X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Fbfd.c;h=81fd17877f73d796fed0032c8e5257f244982659;hb=4b570f12766f3c4eeb527de69d8eedfd59c34b86;hp=9099a2c0fa29417fd578f158f40d6eaa0d2d9498;hpb=b644259ff26970b841479a4e881303ad49e81abe;p=sliver-openvswitch.git diff --git a/lib/bfd.c b/lib/bfd.c index 9099a2c0f..81fd17877 100644 --- a/lib/bfd.c +++ b/lib/bfd.c @@ -16,6 +16,7 @@ #include "bfd.h" #include +#include #include #include "byte-order.h" @@ -160,6 +161,9 @@ struct bfd { uint32_t rmt_disc; /* bfd.RemoteDiscr. */ + uint8_t eth_dst[ETH_ADDR_LEN];/* Ethernet destination address. */ + bool eth_dst_set; /* 'eth_dst' set through database. */ + uint16_t udp_src; /* UDP source port. */ /* All timers in milliseconds. */ @@ -187,29 +191,29 @@ static struct ovs_mutex mutex = OVS_MUTEX_INITIALIZER; static struct hmap all_bfds__ = HMAP_INITIALIZER(&all_bfds__); static struct hmap *const all_bfds OVS_GUARDED_BY(mutex) = &all_bfds__; -static bool bfd_forwarding__(const struct bfd *) OVS_REQ_WRLOCK(mutex); -static bool bfd_in_poll(const struct bfd *) OVS_REQ_WRLOCK(&mutex); -static void bfd_poll(struct bfd *bfd) OVS_REQ_WRLOCK(&mutex); -static const char *bfd_diag_str(enum diag) OVS_REQ_WRLOCK(&mutex); -static const char *bfd_state_str(enum state) OVS_REQ_WRLOCK(&mutex); -static long long int bfd_min_tx(const struct bfd *) OVS_REQ_WRLOCK(&mutex); +static bool bfd_forwarding__(const struct bfd *) OVS_REQUIRES(mutex); +static bool bfd_in_poll(const struct bfd *) OVS_REQUIRES(mutex); +static void bfd_poll(struct bfd *bfd) OVS_REQUIRES(mutex); +static const char *bfd_diag_str(enum diag) OVS_REQUIRES(mutex); +static const char *bfd_state_str(enum state) OVS_REQUIRES(mutex); +static long long int bfd_min_tx(const struct bfd *) OVS_REQUIRES(mutex); static long long int bfd_tx_interval(const struct bfd *) - OVS_REQ_WRLOCK(&mutex); + OVS_REQUIRES(mutex); static long long int bfd_rx_interval(const struct bfd *) - OVS_REQ_WRLOCK(&mutex); -static void bfd_set_next_tx(struct bfd *) OVS_REQ_WRLOCK(&mutex); + OVS_REQUIRES(mutex); +static void bfd_set_next_tx(struct bfd *) OVS_REQUIRES(mutex); static void bfd_set_state(struct bfd *, enum state, enum diag) - OVS_REQ_WRLOCK(&mutex); -static uint32_t generate_discriminator(void) OVS_REQ_WRLOCK(&mutex); + OVS_REQUIRES(mutex); +static uint32_t generate_discriminator(void) OVS_REQUIRES(mutex); static void bfd_put_details(struct ds *, const struct bfd *) - OVS_REQ_WRLOCK(&mutex); + OVS_REQUIRES(mutex); static void bfd_unixctl_show(struct unixctl_conn *, int argc, const char *argv[], void *aux OVS_UNUSED); static void bfd_unixctl_set_forwarding_override(struct unixctl_conn *, int argc, const char *argv[], void *aux OVS_UNUSED); static void log_msg(enum vlog_level, const struct msg *, const char *message, - const struct bfd *) OVS_REQ_WRLOCK(&mutex); + const struct bfd *) OVS_REQUIRES(mutex); static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(20, 20); @@ -258,6 +262,8 @@ bfd_configure(struct bfd *bfd, const char *name, const struct smap *cfg) long long int min_tx, min_rx; bool cpath_down; + const char *hwaddr; + uint8_t ea[ETH_ADDR_LEN]; if (ovsthread_once_start(&once)) { unixctl_command_register("bfd/show", "[interface]", 0, 1, @@ -295,6 +301,8 @@ bfd_configure(struct bfd *bfd, const char *name, const struct smap *cfg) bfd->udp_src = (bfd->udp_src % 16384) + 49152; bfd_set_state(bfd, STATE_DOWN, DIAG_NONE); + + memcpy(bfd->eth_dst, eth_addr_bfd, ETH_ADDR_LEN); } atomic_store(&bfd->check_tnl_key, @@ -329,6 +337,16 @@ bfd_configure(struct bfd *bfd, const char *name, const struct smap *cfg) } bfd_poll(bfd); } + + hwaddr = smap_get(cfg, "bfd_dst_mac"); + if (hwaddr && eth_addr_from_string(hwaddr, ea) && !eth_addr_is_zero(ea)) { + memcpy(bfd->eth_dst, ea, ETH_ADDR_LEN); + bfd->eth_dst_set = true; + } else if (bfd->eth_dst_set) { + memcpy(bfd->eth_dst, eth_addr_bfd, ETH_ADDR_LEN); + bfd->eth_dst_set = false; + } + ovs_mutex_unlock(&mutex); return bfd; } @@ -429,8 +447,8 @@ bfd_put_packet(struct bfd *bfd, struct ofpbuf *p, ofpbuf_reserve(p, 2); /* Properly align after the ethernet header. */ eth = ofpbuf_put_uninit(p, sizeof *eth); - memcpy(eth->eth_dst, eth_addr_broadcast, ETH_ADDR_LEN); memcpy(eth->eth_src, eth_src, ETH_ADDR_LEN); + memcpy(eth->eth_dst, bfd->eth_dst, ETH_ADDR_LEN); eth->eth_type = htons(ETH_TYPE_IP); ip = ofpbuf_put_zeros(p, sizeof *ip); @@ -483,6 +501,10 @@ bfd_should_process_flow(const struct bfd *bfd, const struct flow *flow, struct flow_wildcards *wc) { bool check_tnl_key; + memset(&wc->masks.dl_dst, 0xff, sizeof wc->masks.dl_dst); + if (bfd->eth_dst_set && memcmp(bfd->eth_dst, flow->dl_dst, ETH_ADDR_LEN)) { + return false; + } memset(&wc->masks.nw_proto, 0xff, sizeof wc->masks.nw_proto); memset(&wc->masks.tp_dst, 0xff, sizeof wc->masks.tp_dst); @@ -493,7 +515,7 @@ bfd_should_process_flow(const struct bfd *bfd, const struct flow *flow, } return (flow->dl_type == htons(ETH_TYPE_IP) && flow->nw_proto == IPPROTO_UDP - && flow->tp_dst == htons(3784) + && flow->tp_dst == htons(BFD_DEST_PORT) && (check_tnl_key || flow->tunnel.tun_id == htonll(0))); } @@ -661,7 +683,7 @@ out: } static bool -bfd_forwarding__(const struct bfd *bfd) OVS_REQ_WRLOCK(mutex) +bfd_forwarding__(const struct bfd *bfd) OVS_REQUIRES(mutex) { if (bfd->forwarding_override != -1) { return bfd->forwarding_override == 1; @@ -675,13 +697,13 @@ bfd_forwarding__(const struct bfd *bfd) OVS_REQ_WRLOCK(mutex) /* Helpers. */ static bool -bfd_in_poll(const struct bfd *bfd) OVS_REQ_WRLOCK(mutex) +bfd_in_poll(const struct bfd *bfd) OVS_REQUIRES(mutex) { return (bfd->flags & FLAG_POLL) != 0; } static void -bfd_poll(struct bfd *bfd) OVS_REQ_WRLOCK(mutex) +bfd_poll(struct bfd *bfd) OVS_REQUIRES(mutex) { if (bfd->state > STATE_DOWN && !bfd_in_poll(bfd) && !(bfd->flags & FLAG_FINAL)) { @@ -694,7 +716,7 @@ bfd_poll(struct bfd *bfd) OVS_REQ_WRLOCK(mutex) } static long long int -bfd_min_tx(const struct bfd *bfd) OVS_REQ_WRLOCK(mutex) +bfd_min_tx(const struct bfd *bfd) OVS_REQUIRES(mutex) { /* RFC 5880 Section 6.8.3 * When bfd.SessionState is not Up, the system MUST set @@ -706,20 +728,20 @@ bfd_min_tx(const struct bfd *bfd) OVS_REQ_WRLOCK(mutex) } static long long int -bfd_tx_interval(const struct bfd *bfd) OVS_REQ_WRLOCK(mutex) +bfd_tx_interval(const struct bfd *bfd) OVS_REQUIRES(mutex) { long long int interval = bfd_min_tx(bfd); return MAX(interval, bfd->rmt_min_rx); } static long long int -bfd_rx_interval(const struct bfd *bfd) OVS_REQ_WRLOCK(mutex) +bfd_rx_interval(const struct bfd *bfd) OVS_REQUIRES(mutex) { return MAX(bfd->min_rx, bfd->rmt_min_tx); } static void -bfd_set_next_tx(struct bfd *bfd) OVS_REQ_WRLOCK(mutex) +bfd_set_next_tx(struct bfd *bfd) OVS_REQUIRES(mutex) { long long int interval = bfd_tx_interval(bfd); interval -= interval * random_range(26) / 100; @@ -795,7 +817,7 @@ bfd_diag_str(enum diag diag) { static void log_msg(enum vlog_level level, const struct msg *p, const char *message, - const struct bfd *bfd) OVS_REQ_WRLOCK(mutex) + const struct bfd *bfd) OVS_REQUIRES(mutex) { struct ds ds = DS_EMPTY_INITIALIZER; @@ -827,7 +849,7 @@ log_msg(enum vlog_level level, const struct msg *p, const char *message, static void bfd_set_state(struct bfd *bfd, enum state state, enum diag diag) - OVS_REQ_WRLOCK(mutex) + OVS_REQUIRES(mutex) { if (diag == DIAG_NONE && bfd->cpath_down) { diag = DIAG_CPATH_DOWN; @@ -889,7 +911,7 @@ generate_discriminator(void) } static struct bfd * -bfd_find_by_name(const char *name) OVS_REQ_WRLOCK(mutex) +bfd_find_by_name(const char *name) OVS_REQUIRES(mutex) { struct bfd *bfd; @@ -902,7 +924,7 @@ bfd_find_by_name(const char *name) OVS_REQ_WRLOCK(mutex) } static void -bfd_put_details(struct ds *ds, const struct bfd *bfd) OVS_REQ_WRLOCK(mutex) +bfd_put_details(struct ds *ds, const struct bfd *bfd) OVS_REQUIRES(mutex) { ds_put_format(ds, "\tForwarding: %s\n", bfd_forwarding__(bfd) ? "true" : "false");