From patchwork Wed Nov 25 09:59:38 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 1405969 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.133; helo=hemlock.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=VGxt4JhP; dkim-atps=neutral Received: from hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4CgxG06k4Pz9s0b for ; Wed, 25 Nov 2020 21:00:08 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by hemlock.osuosl.org (Postfix) with ESMTP id C98C18754A; Wed, 25 Nov 2020 10:00:06 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from hemlock.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id igZbVB+FnJK4; Wed, 25 Nov 2020 10:00:01 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by hemlock.osuosl.org (Postfix) with ESMTP id 886DB873E4; Wed, 25 Nov 2020 10:00:01 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 68A6AC163C; Wed, 25 Nov 2020 10:00:01 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from whitealder.osuosl.org (smtp1.osuosl.org [140.211.166.138]) by lists.linuxfoundation.org (Postfix) with ESMTP id 5FF7EC1836 for ; Wed, 25 Nov 2020 10:00:00 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by whitealder.osuosl.org (Postfix) with ESMTP id 20AF186DDA for ; Wed, 25 Nov 2020 10:00:00 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from whitealder.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id jI7njrq7PJQP for ; Wed, 25 Nov 2020 09:59:58 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [63.128.21.124]) by whitealder.osuosl.org (Postfix) with ESMTPS id A96AF86DD7 for ; Wed, 25 Nov 2020 09:59:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1606298396; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=czOzk4PUODrRXiYHHMuX323HNDf6xC+9QuyhtdvnilE=; b=VGxt4JhPmnKtblzz/5h55IySEPvldFyFgKr8qaFJfaVXfuQrbdahNVjRyfZkycYHy1d0kG 1Odf0YXIvF2wsRyL5x5FhL3ZKjcoNirAL7Kr4L/+ZFji8dAMxEyGWfaZwyfybqJg+i9wTs X9bpSHoi3nmLNkg/X+fbxKfczT93nSc= Received: from mail-ed1-f72.google.com (mail-ed1-f72.google.com [209.85.208.72]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-548-D1gw8cuYPpa5y13E30_X2A-1; Wed, 25 Nov 2020 04:59:53 -0500 X-MC-Unique: D1gw8cuYPpa5y13E30_X2A-1 Received: by mail-ed1-f72.google.com with SMTP id d3so846843eds.3 for ; Wed, 25 Nov 2020 01:59:53 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=czOzk4PUODrRXiYHHMuX323HNDf6xC+9QuyhtdvnilE=; b=rHMrxEzye4Az7I/XTNSzJGwcr8Tf/5o6dcd7hZqb0vOtJN9s2f3aRjuiiXmPXMAYSq kkaoIRtKu3njX/KqgdyE/7LHql0jPpYBdomFjFnX9fQEx75AzQKh2EiqAcV8ySzjIZfx mWUzigeTLpTnW8PmznU0GM//GTDMC7+dX0MCWeZ2xGfeRMjXtReczgiI8hZazHrrX41h QkvtEaGWODsRqqCKC0FSdiJKNnzHB4EVuEpaD96M7kCfEATucOJ/M7pDj4F9jjWV8hIM qthza8ymTvMIrXdK8dPxUHer9QVdM5WUdpaPnttzSvEYmwrxwfkyDMXOoIuJcYp2FY0a bLwQ== X-Gm-Message-State: AOAM533i9z/1Z+sII+v0BC1E3XIjSW/p1yzNmx6ENLy4JRTQQrgUCimY uRGAQ1Mx6fYEQs8uxIhRZyWiGe2cLSiCM0QwZ3k6t5zdhIvmXvxkAJkgOUMv0s90YFhBePgurZS D8nsqeyLlViVLCFWSNt4BjfFDNj02laWv0nmrBrOYHX0DxCg+Pah8EnddCEFx1ljCHLN+xEH8Ke 4= X-Received: by 2002:a17:907:262d:: with SMTP id aq13mr2447721ejc.484.1606298391698; Wed, 25 Nov 2020 01:59:51 -0800 (PST) X-Google-Smtp-Source: ABdhPJzdpwY7huTqbGDDhc9J3qXZgfDSupStvSrWzVrmnM2EF6sJcWEbwlZYxE4DM73gxzuulCF7/g== X-Received: by 2002:a17:907:262d:: with SMTP id aq13mr2447690ejc.484.1606298391149; Wed, 25 Nov 2020 01:59:51 -0800 (PST) Received: from lore-desk.redhat.com ([151.66.8.153]) by smtp.gmail.com with ESMTPSA id g13sm936862edy.7.2020.11.25.01.59.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 25 Nov 2020 01:59:50 -0800 (PST) From: Lorenzo Bianconi To: dev@openvswitch.org Date: Wed, 25 Nov 2020 10:59:38 +0100 Message-Id: <2027bdac477568be52ece9a3461453bd312f44af.1606298055.git.lorenzo.bianconi@redhat.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: References: MIME-Version: 1.0 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=lorenzo.bianconi@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Cc: trozet@redhat.com Subject: [ovs-dev] [PATCH ovn 1/4] controller: introduce BFD tx path in ovn-controller X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" introduce BFD tx path in ovn-controller. introduce BFD table in nb/sb dbs in order to configure BFD tx path ovn-controller Signed-off-by: Lorenzo Bianconi --- controller/ovn-controller.c | 1 + controller/pinctrl.c | 288 +++++++++++++++++++++++++++++++++++- controller/pinctrl.h | 2 + lib/ovn-l7.h | 19 +++ northd/ovn-northd.c | 118 +++++++++++++++ ovn-nb.ovsschema | 19 ++- ovn-nb.xml | 62 ++++++++ ovn-sb.ovsschema | 23 ++- ovn-sb.xml | 74 +++++++++ 9 files changed, 601 insertions(+), 5 deletions(-) diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c index bea2c8eb6..0b55605bb 100644 --- a/controller/ovn-controller.c +++ b/controller/ovn-controller.c @@ -2771,6 +2771,7 @@ main(int argc, char *argv[]) ovnsb_idl_loop.idl), sbrec_service_monitor_table_get( ovnsb_idl_loop.idl), + sbrec_bfd_table_get(ovnsb_idl_loop.idl), br_int, chassis, &runtime_data->local_datapaths, &runtime_data->active_tunnels); diff --git a/controller/pinctrl.c b/controller/pinctrl.c index 919eae4f8..0e80c00c1 100644 --- a/controller/pinctrl.c +++ b/controller/pinctrl.c @@ -323,6 +323,18 @@ put_load(uint64_t value, enum mf_field_id dst, int ofs, int n_bits, static void notify_pinctrl_main(void); static void notify_pinctrl_handler(void); +static bool bfd_monitor_should_inject(void); +static void bfd_monitor_wait(long long int timeout); +static void bfd_monitor_init(void); +static void bfd_monitor_destroy(void); +static void bfd_monitor_send_msg(struct rconn *swconn, long long int *bfd_time) + OVS_REQUIRES(pinctrl_mutex); +static void bfd_monitor_run(const struct sbrec_bfd_table *bfd_table, + struct ovsdb_idl_index *sbrec_port_binding_by_name, + const struct sbrec_chassis *chassis, + const struct sset *active_tunnels) + OVS_REQUIRES(pinctrl_mutex); + COVERAGE_DEFINE(pinctrl_drop_put_mac_binding); COVERAGE_DEFINE(pinctrl_drop_buffered_packets_map); COVERAGE_DEFINE(pinctrl_drop_controller_event); @@ -487,6 +499,7 @@ pinctrl_init(void) ip_mcast_snoop_init(); init_put_vport_bindings(); init_svc_monitors(); + bfd_monitor_init(); pinctrl.br_int_name = NULL; pinctrl_handler_seq = seq_create(); pinctrl_main_seq = seq_create(); @@ -3037,6 +3050,8 @@ pinctrl_handler(void *arg_) swconn = rconn_create(5, 0, DSCP_DEFAULT, 1 << OFP15_VERSION); while (!latch_is_set(&pctrl->pinctrl_thread_exit)) { + long long int bfd_time = LLONG_MAX; + if (pctrl->br_int_name) { if (!br_int_name || strcmp(br_int_name, pctrl->br_int_name)) { free(br_int_name); @@ -3088,6 +3103,7 @@ pinctrl_handler(void *arg_) send_ipv6_ras(swconn, &send_ipv6_ra_time); send_ipv6_prefixd(swconn, &send_prefixd_time); send_mac_binding_buffered_pkts(swconn); + bfd_monitor_send_msg(swconn, &bfd_time); ovs_mutex_unlock(&pinctrl_mutex); ip_mcast_querier_run(swconn, &send_mcast_query_time); @@ -3105,6 +3121,7 @@ pinctrl_handler(void *arg_) ip_mcast_querier_wait(send_mcast_query_time); svc_monitors_wait(svc_monitors_next_run_time); ipv6_prefixd_wait(send_prefixd_time); + bfd_monitor_wait(bfd_time); new_seq = seq_read(pinctrl_handler_seq); seq_wait(pinctrl_handler_seq, new_seq); @@ -3154,6 +3171,7 @@ pinctrl_run(struct ovsdb_idl_txn *ovnsb_idl_txn, const struct sbrec_dns_table *dns_table, const struct sbrec_controller_event_table *ce_table, const struct sbrec_service_monitor_table *svc_mon_table, + const struct sbrec_bfd_table *bfd_table, const struct ovsrec_bridge *br_int, const struct sbrec_chassis *chassis, const struct hmap *local_datapaths, @@ -3184,6 +3202,8 @@ pinctrl_run(struct ovsdb_idl_txn *ovnsb_idl_txn, local_datapaths); sync_svc_monitors(ovnsb_idl_txn, svc_mon_table, sbrec_port_binding_by_name, chassis); + bfd_monitor_run(bfd_table, sbrec_port_binding_by_name, chassis, + active_tunnels); ovs_mutex_unlock(&pinctrl_mutex); } @@ -3727,6 +3747,7 @@ pinctrl_destroy(void) destroy_dns_cache(); ip_mcast_snoop_destroy(); destroy_svc_monitors(); + bfd_monitor_destroy(); seq_destroy(pinctrl_main_seq); seq_destroy(pinctrl_handler_seq); } @@ -5516,7 +5537,8 @@ may_inject_pkts(void) !shash_is_empty(&send_garp_rarp_data) || ipv6_prefixd_should_inject() || !ovs_list_is_empty(&mcast_query_list) || - !ovs_list_is_empty(&buffered_mac_bindings)); + !ovs_list_is_empty(&buffered_mac_bindings) || + bfd_monitor_should_inject()); } static void @@ -6303,6 +6325,270 @@ sync_svc_monitors(struct ovsdb_idl_txn *ovnsb_idl_txn, } +static struct hmap bfd_monitor_map; + +struct bfd_entry { + struct hmap_node node; + + /* L2 source address */ + struct eth_addr src_mac; + /* IPv4 source address */ + ovs_be32 ip_src; + /* IPv4 destination address */ + ovs_be32 ip_dst; + /* RFC 5881 section 4 + * The source port MUST be in the range 49152 through 65535. + * The same UDP source port number MUST be used for all BFD + * Control packets associated with a particular session. + * The source port number SHOULD be unique among all BFD + * sessions on the system + */ + uint16_t udp_src; + ovs_be32 disc; + + int64_t port_key; + int64_t metadata; + + long long int last_update; + long long int next_tx; +}; + +static void +bfd_monitor_init(void) +{ + hmap_init(&bfd_monitor_map); +} + +static void +bfd_monitor_destroy(void) +{ + hmap_destroy(&bfd_monitor_map); +} + +static struct bfd_entry * +pinctrl_find_bfd_monitor_entry_by_port(char *ip, uint16_t port) +{ + struct bfd_entry *entry; + HMAP_FOR_EACH_WITH_HASH (entry, node, hash_string(ip, 0), + &bfd_monitor_map) { + if (entry->udp_src == port) { + return entry; + } + } + return NULL; +} + +static bool +bfd_monitor_should_inject(void) +{ + long long int cur_time = time_msec(); + struct bfd_entry *entry; + + HMAP_FOR_EACH (entry, node, &bfd_monitor_map) { + if (entry->next_tx < cur_time) { + return true; + } + } + return false; +} + +static void +bfd_monitor_wait(long long int timeout) +{ + if (!hmap_is_empty(&bfd_monitor_map)) { + poll_timer_wait_until(timeout); + } +} + +static void +bfd_monitor_put_bfd_msg(struct bfd_entry *entry, struct dp_packet *packet) +{ + struct udp_header *udp; + struct bfd_msg *msg; + + dp_packet_reserve(packet, 2); + struct eth_header *eth = dp_packet_put_uninit(packet, sizeof *eth); + eth->eth_dst = eth_addr_broadcast; + eth->eth_src = entry->src_mac; + eth->eth_type = htons(ETH_TYPE_IP); + + struct ip_header *ip = dp_packet_put_zeros(packet, sizeof *ip); + ip->ip_ihl_ver = IP_IHL_VER(5, 4); + ip->ip_tot_len = htons(sizeof *ip + sizeof *udp + sizeof *msg); + ip->ip_ttl = MAXTTL; + ip->ip_tos = IPTOS_PREC_INTERNETCONTROL; + ip->ip_proto = IPPROTO_UDP; + put_16aligned_be32(&ip->ip_src, entry->ip_src); + put_16aligned_be32(&ip->ip_dst, entry->ip_dst); + /* Checksum has already been zeroed by put_zeros call. */ + ip->ip_csum = csum(ip, sizeof *ip); + + udp = dp_packet_put_zeros(packet, sizeof *udp); + udp->udp_src = htons(entry->udp_src); + udp->udp_dst = htons(BFD_DEST_PORT); + udp->udp_len = htons(sizeof *udp + sizeof *msg); + + msg = dp_packet_put_uninit(packet, sizeof *msg); + msg->vers_diag = (BFD_VERSION << 5); + msg->length = BFD_PACKET_LEN; +} + +static void +bfd_monitor_send_msg(struct rconn *swconn, long long int *bfd_time) + OVS_REQUIRES(pinctrl_mutex) +{ + long long int cur_time = time_msec(); + struct bfd_entry *entry; + + HMAP_FOR_EACH (entry, node, &bfd_monitor_map) { + if (cur_time < entry->next_tx) { + goto next; + } + + uint64_t packet_stub[256 / 8]; + struct dp_packet packet; + dp_packet_use_stub(&packet, packet_stub, sizeof packet_stub); + bfd_monitor_put_bfd_msg(entry, &packet); + + uint64_t ofpacts_stub[4096 / 8]; + struct ofpbuf ofpacts = OFPBUF_STUB_INITIALIZER(ofpacts_stub); + + /* Set MFF_LOG_DATAPATH and MFF_LOG_INPORT. */ + uint32_t dp_key = entry->metadata; + uint32_t port_key = entry->port_key; + put_load(dp_key, MFF_LOG_DATAPATH, 0, 64, &ofpacts); + put_load(port_key, MFF_LOG_INPORT, 0, 32, &ofpacts); + put_load(1, MFF_LOG_FLAGS, MLF_LOCAL_ONLY_BIT, 1, &ofpacts); + struct ofpact_resubmit *resubmit = ofpact_put_RESUBMIT(&ofpacts); + resubmit->in_port = OFPP_CONTROLLER; + resubmit->table_id = OFTABLE_LOG_INGRESS_PIPELINE; + + struct ofputil_packet_out po = { + .packet = dp_packet_data(&packet), + .packet_len = dp_packet_size(&packet), + .buffer_id = UINT32_MAX, + .ofpacts = ofpacts.data, + .ofpacts_len = ofpacts.size, + }; + + match_set_in_port(&po.flow_metadata, OFPP_CONTROLLER); + enum ofp_version version = rconn_get_version(swconn); + enum ofputil_protocol proto = + ofputil_protocol_from_ofp_version(version); + queue_msg(swconn, ofputil_encode_packet_out(&po, proto)); + dp_packet_uninit(&packet); + ofpbuf_uninit(&ofpacts); + + entry->next_tx = cur_time + 5000; +next: + if (*bfd_time > entry->next_tx) { + *bfd_time = entry->next_tx; + } + } +} + +#define BFD_MONITOR_STALE_TIMEOUT 180000LL +static void +bfd_monitor_run(const struct sbrec_bfd_table *bfd_table, + struct ovsdb_idl_index *sbrec_port_binding_by_name, + const struct sbrec_chassis *chassis, + const struct sset *active_tunnels) + OVS_REQUIRES(pinctrl_mutex) +{ + long long int cur_time = time_msec(); + bool changed = false; + + const struct sbrec_bfd *bt; + SBREC_BFD_TABLE_FOR_EACH (bt, bfd_table) { + const struct sbrec_port_binding *pb + = lport_lookup_by_name(sbrec_port_binding_by_name, + bt->logical_port); + if (!pb) { + continue; + } + + struct bfd_entry *entry = pinctrl_find_bfd_monitor_entry_by_port( + bt->dst_ip, bt->src_port); + if (!entry) { + ovs_be32 ip_dst, ip_src = htonl(BFD_DEFAULT_SRC_IP); + struct eth_addr ea = eth_addr_zero; + int i; + + if (!ip_parse(bt->dst_ip, &ip_dst)) { + continue; + } + + const char *peer_s = smap_get(&pb->options, "peer"); + if (!peer_s) { + continue; + } + + const struct sbrec_port_binding *peer + = lport_lookup_by_name(sbrec_port_binding_by_name, peer_s); + if (!peer) { + continue; + } + + char *redirect_name = xasprintf("cr-%s", pb->logical_port); + bool resident = lport_is_chassis_resident( + sbrec_port_binding_by_name, chassis, active_tunnels, + redirect_name); + free(redirect_name); + if (!resident && strcmp(pb->type, "l3gateway") && + pb->chassis != chassis) { + continue; + } + + for (i = 0; i < pb->n_mac; i++) { + struct lport_addresses laddrs; + + if (!extract_lsp_addresses(pb->mac[i], &laddrs)) { + continue; + } + + ea = laddrs.ea; + if (laddrs.n_ipv4_addrs > 0) { + ip_src = laddrs.ipv4_addrs[0].addr; + destroy_lport_addresses(&laddrs); + break; + } + destroy_lport_addresses(&laddrs); + } + + if (eth_addr_is_zero(ea)) { + continue; + } + + entry = xzalloc(sizeof *entry); + entry->src_mac = ea; + entry->ip_src = ip_src; + entry->ip_dst = ip_dst; + entry->udp_src = bt->src_port; + entry->disc = htonl(bt->disc); + entry->next_tx = cur_time; + entry->metadata = pb->datapath->tunnel_key; + entry->port_key = pb->tunnel_key; + + uint32_t hash = hash_string(bt->dst_ip, 0); + hmap_insert(&bfd_monitor_map, &entry->node, hash); + changed = true; + } + entry->last_update = cur_time; + } + + struct bfd_entry *entry, *next_entry; + HMAP_FOR_EACH_SAFE (entry, next_entry, node, &bfd_monitor_map) { + if (entry->last_update + BFD_MONITOR_STALE_TIMEOUT < cur_time) { + hmap_remove(&bfd_monitor_map, &entry->node); + free(entry); + } + } + + if (changed) { + notify_pinctrl_handler(); + } +} + static uint16_t get_random_src_port(void) { diff --git a/controller/pinctrl.h b/controller/pinctrl.h index 4b101ec92..8555d983d 100644 --- a/controller/pinctrl.h +++ b/controller/pinctrl.h @@ -31,6 +31,7 @@ struct sbrec_chassis; struct sbrec_dns_table; struct sbrec_controller_event_table; struct sbrec_service_monitor_table; +struct sbrec_bfd_table; void pinctrl_init(void); void pinctrl_run(struct ovsdb_idl_txn *ovnsb_idl_txn, @@ -44,6 +45,7 @@ void pinctrl_run(struct ovsdb_idl_txn *ovnsb_idl_txn, const struct sbrec_dns_table *, const struct sbrec_controller_event_table *, const struct sbrec_service_monitor_table *, + const struct sbrec_bfd_table *, const struct ovsrec_bridge *, const struct sbrec_chassis *, const struct hmap *local_datapaths, const struct sset *active_tunnels); diff --git a/lib/ovn-l7.h b/lib/ovn-l7.h index c84a0e7a9..d00982449 100644 --- a/lib/ovn-l7.h +++ b/lib/ovn-l7.h @@ -26,6 +26,25 @@ #include "hash.h" #include "ovn/logical-fields.h" +#define BFD_PACKET_LEN 24 +#define BFD_DEST_PORT 3784 +#define BFD_VERSION 1 +#define BFD_DEFAULT_SRC_IP 0xA9FE0101 /* 169.254.1.1 */ +#define BFD_DEFAULT_DST_IP 0xA9FE0100 /* 169.254.1.0 */ + +struct bfd_msg { + uint8_t vers_diag; + uint8_t flags; + uint8_t mult; + uint8_t length; + ovs_be32 my_disc; + ovs_be32 your_disc; + ovs_be32 min_tx; + ovs_be32 min_rx; + ovs_be32 min_rx_echo; +}; +BUILD_ASSERT_DECL(BFD_PACKET_LEN == sizeof(struct bfd_msg)); + /* Generic options map which is used to store dhcpv4 opts and dhcpv6 opts. */ struct gen_opts_map { struct hmap_node hmap_node; diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c index 47a177c99..d25f370ae 100644 --- a/northd/ovn-northd.c +++ b/northd/ovn-northd.c @@ -69,6 +69,7 @@ struct northd_context { struct ovsdb_idl_index *sbrec_ha_chassis_grp_by_name; struct ovsdb_idl_index *sbrec_mcast_group_by_name_dp; struct ovsdb_idl_index *sbrec_ip_mcast_by_dp; + struct ovsdb_idl_index *sbrec_bfd_by_logical_port; }; struct northd_state { @@ -91,6 +92,8 @@ static bool controller_event_en; static bool check_lsp_is_up; +static bool bfd_en; + /* MAC allocated for service monitor usage. Just one mac is allocated * for this purpose and ovn-controller's on each chassis will make use * of this mac when sending out the packets to monitor the services @@ -11322,6 +11325,112 @@ build_lflows(struct northd_context *ctx, struct hmap *datapaths, } } +static struct ovsdb_idl_index * +bfd_index_create(struct ovsdb_idl *idl) +{ + return ovsdb_idl_index_create2(idl, &sbrec_bfd_col_logical_port, + &sbrec_bfd_col_dst_ip); +} + +static const struct sbrec_bfd * +bfd_port_lookup(struct ovsdb_idl_index *bfd_index, + const char *logical_port, const char *dst_ip) +{ + struct sbrec_bfd *target = sbrec_bfd_index_init_row(bfd_index); + sbrec_bfd_index_set_logical_port(target, logical_port); + sbrec_bfd_index_set_dst_ip(target, dst_ip); + + struct sbrec_bfd *bfd_entry = sbrec_bfd_index_find(bfd_index, target); + sbrec_bfd_index_destroy_row(target); + + return bfd_entry; +} + +struct bfd_entry { + struct hmap_node hmap_node; + + char *logical_port; + char *dst_ip; + + const struct sbrec_bfd *sb_bt; + bool found; +}; + +static void +build_bfd_table(struct northd_context *ctx) +{ + const struct nbrec_nb_global *nb = nbrec_nb_global_first(ctx->ovnnb_idl); + + bfd_en = smap_get_bool(&nb->options, "bfd", false); + if (!bfd_en) { + return; + } + + struct hmap sb_only = HMAP_INITIALIZER(&sb_only); + struct bfd_entry *bfd_e, *next_bfd_e; + const struct sbrec_bfd *sb_bt; + + SBREC_BFD_FOR_EACH (sb_bt, ctx->ovnsb_idl) { + bfd_e = xmalloc(sizeof *bfd_e); + bfd_e->logical_port = xstrdup(sb_bt->logical_port); + bfd_e->dst_ip = xstrdup(sb_bt->dst_ip); + bfd_e->sb_bt = sb_bt; + hmap_insert(&sb_only, &bfd_e->hmap_node, + hash_string(bfd_e->dst_ip, 0)); + } + + const struct nbrec_bfd *nb_bt; + NBREC_BFD_FOR_EACH (nb_bt, ctx->ovnnb_idl) { + sb_bt = bfd_port_lookup(ctx->sbrec_bfd_by_logical_port, + nb_bt->logical_port, nb_bt->dst_ip); + if (!sb_bt) { + sb_bt = sbrec_bfd_insert(ctx->ovnsb_txn); + sbrec_bfd_set_logical_port(sb_bt, nb_bt->logical_port); + sbrec_bfd_set_dst_ip(sb_bt, nb_bt->dst_ip); + sbrec_bfd_set_disc(sb_bt, 1 + random_uint32()); + /* RFC 5881 section 4 + * The source port MUST be in the range 49152 through 65535. + * The same UDP source port number MUST be used for all BFD + * Control packets associated with a particular session. + * The source port number SHOULD be unique among all BFD + * sessions on the system + */ + uint16_t udp_src = random_range(16383) + 49152; + sbrec_bfd_set_src_port(sb_bt, udp_src); + sbrec_bfd_set_status(sb_bt, "down"); + sbrec_bfd_set_min_tx(sb_bt, nb_bt->min_tx); + sbrec_bfd_set_min_rx(sb_bt, nb_bt->min_rx); + sbrec_bfd_set_detect_mult(sb_bt, nb_bt->detect_mult); + } else if (strcmp(sb_bt->status, nb_bt->status)) { + if (!strcmp(nb_bt->status, "admin_down") || + !strcmp(sb_bt->status, "admin_down")) { + sbrec_bfd_set_status(sb_bt, nb_bt->status); + } else { + nbrec_bfd_set_status(nb_bt, sb_bt->status); + } + } + HMAP_FOR_EACH_WITH_HASH (bfd_e, hmap_node, + hash_string(nb_bt->dst_ip, 0), &sb_only) { + if (!strcmp(bfd_e->logical_port, nb_bt->logical_port) && + !strcmp(bfd_e->dst_ip, nb_bt->dst_ip)) { + bfd_e->found = true; + break; + } + } + } + + HMAP_FOR_EACH_SAFE (bfd_e, next_bfd_e, hmap_node, &sb_only) { + if (!bfd_e->found && bfd_e->sb_bt) { + sbrec_bfd_delete(bfd_e->sb_bt); + } + free(bfd_e->logical_port); + free(bfd_e->dst_ip); + hmap_remove(&sb_only, &bfd_e->hmap_node); + free(bfd_e); + } + hmap_destroy(&sb_only); +} + static void sync_address_set(struct northd_context *ctx, const char *name, const char **addrs, size_t n_addrs, @@ -12117,6 +12226,7 @@ ovnnb_db_run(struct northd_context *ctx, build_ip_mcast(ctx, datapaths); build_mcast_groups(ctx, datapaths, ports, &mcast_groups, &igmp_groups); build_meter_groups(ctx, &meter_groups); + build_bfd_table(ctx); build_lflows(ctx, datapaths, ports, &port_groups, &mcast_groups, &igmp_groups, &meter_groups, &lbs); ovn_update_ipv6_prefix(ports); @@ -13069,6 +13179,10 @@ main(int argc, char *argv[]) add_column_noalert(ovnsb_idl_loop.idl, &sbrec_load_balancer_col_external_ids); + ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_bfd_col_logical_port); + ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_bfd_col_dst_ip); + ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_bfd_col_status); + struct ovsdb_idl_index *sbrec_chassis_by_name = chassis_index_create(ovnsb_idl_loop.idl); @@ -13081,6 +13195,9 @@ main(int argc, char *argv[]) struct ovsdb_idl_index *sbrec_ip_mcast_by_dp = ip_mcast_index_create(ovnsb_idl_loop.idl); + struct ovsdb_idl_index *sbrec_bfd_by_logical_port + = bfd_index_create(ovnsb_idl_loop.idl); + unixctl_command_register("sb-connection-status", "", 0, 0, ovn_conn_show, ovnsb_idl_loop.idl); @@ -13113,6 +13230,7 @@ main(int argc, char *argv[]) .sbrec_ha_chassis_grp_by_name = sbrec_ha_chassis_grp_by_name, .sbrec_mcast_group_by_name_dp = sbrec_mcast_group_by_name_dp, .sbrec_ip_mcast_by_dp = sbrec_ip_mcast_by_dp, + .sbrec_bfd_by_logical_port = sbrec_bfd_by_logical_port, }; if (!state.had_lock && ovsdb_idl_has_lock(ovnsb_idl_loop.idl)) { diff --git a/ovn-nb.ovsschema b/ovn-nb.ovsschema index 269e3a888..fef67e70e 100644 --- a/ovn-nb.ovsschema +++ b/ovn-nb.ovsschema @@ -1,7 +1,7 @@ { "name": "OVN_Northbound", - "version": "5.28.0", - "cksum": "610359755 26847", + "version": "5.29.0", + "cksum": "3632295919 27598", "tables": { "NB_Global": { "columns": { @@ -519,5 +519,20 @@ "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}}, "indexes": [["name"]], + "isRoot": true}, + "BFD": { + "columns": { + "logical_port": {"type": "string"}, + "dst_ip": {"type": "string"}, + "min_tx": {"type": {"key": {"type": "integer"}}}, + "min_rx": {"type": {"key": {"type": "integer"}}}, + "detect_mult": {"type": {"key": {"type": "integer"}}}, + "status": { + "type": {"key": {"type": "string", + "enum": ["set", ["down", "init", "up", "admin_down"]]}}}, + "options": { + "type": {"key": "string", "value": "string", + "min": 0, "max": "unlimited"}}}, + "indexes": [["logical_port", "dst_ip"]], "isRoot": true}} } diff --git a/ovn-nb.xml b/ovn-nb.xml index a457b9cee..ac5192609 100644 --- a/ovn-nb.xml +++ b/ovn-nb.xml @@ -3682,4 +3682,66 @@ + + +

+ Contains BFD parameter for ovn-controller bfd configuration +

+ + + + OVN logical port when BFD engine is running. + + + + BFD peer IP address. + + + + This is the minimum interval, in milliseconds, that the local + system would like to use when transmitting BFD Control packets, + less any jitter applied. The value zero is reserved. + + + + This is the minimum interval, in milliseconds, between received + BFD Control packets that this system is capable of supporting, + less any jitter applied by the sender. If this value is zero, + the transmitting system does not want the remote system to send + any periodic BFD Control packets. + + + + Detection time multiplier. The negotiated transmit interval, + multiplied by this value, provides the Detection Time for the + receiving system in Asynchronous mode. + + + + Reserved for future use. + + + + + +

+ BFD port logical states. Possible values are: +

    +
  • + admin_down +
  • +
  • + down +
  • +
  • + init +
  • +
  • + up +
  • +
+

+
+
+
diff --git a/ovn-sb.ovsschema b/ovn-sb.ovsschema index a1ee8d8d1..6cc4e066e 100644 --- a/ovn-sb.ovsschema +++ b/ovn-sb.ovsschema @@ -1,7 +1,7 @@ { "name": "OVN_Southbound", - "version": "2.11.0", - "cksum": "455413803 23814", + "version": "2.12.0", + "cksum": "164441880 24843", "tables": { "SB_Global": { "columns": { @@ -470,6 +470,25 @@ "external_ids": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}}, + "isRoot": true}, + "BFD": { + "columns": { + "src_port": {"type": {"key": {"type": "integer", + "minInteger": 49152, + "maxInteger": 65535}}}, + "disc": {"type": {"key": {"type": "integer"}}}, + "logical_port": {"type": "string"}, + "dst_ip": {"type": "string"}, + "min_tx": {"type": {"key": {"type": "integer"}}}, + "min_rx": {"type": {"key": {"type": "integer"}}}, + "detect_mult": {"type": {"key": {"type": "integer"}}}, + "status": { + "type": {"key": {"type": "string", + "enum": ["set", ["down", "init", "up", "admin_down"]]}}}, + "options": { + "type": {"key": "string", "value": "string", + "min": 0, "max": "unlimited"}}}, + "indexes": [["logical_port", "dst_ip", "src_port", "disc"]], "isRoot": true} } } diff --git a/ovn-sb.xml b/ovn-sb.xml index 4c6df3fef..49a0069f3 100644 --- a/ovn-sb.xml +++ b/ovn-sb.xml @@ -4211,4 +4211,78 @@ tcp.flags = RST; + + +

+ Contains BFD parameter for ovn-controller bfd configuration +

+ + + + udp source port used in bfd control packets. + The source port MUST be in the range 49152 through 65535 + (RFC5881 section 4). + + + + A unique, nonzero discriminator value generated by the transmitting + system, used to demultiplex multiple BFD sessions between the same pair + of systems. + + + + OVN logical port when BFD engine is running. + + + + BFD peer IP address. + + + + This is the minimum interval, in milliseconds, that the local + system would like to use when transmitting BFD Control packets, + less any jitter applied. The value zero is reserved. + + + + This is the minimum interval, in milliseconds, between received + BFD Control packets that this system is capable of supporting, + less any jitter applied by the sender. If this value is zero, + the transmitting system does not want the remote system to send + any periodic BFD Control packets. + + + + Detection time multiplier. The negotiated transmit interval, + multiplied by this value, provides the Detection Time for the + receiving system in Asynchronous mode. + + + + Reserved for future use. + + + + + +

+ BFD port logical states. Possible values are: +

    +
  • + admin_down +
  • +
  • + down +
  • +
  • + init +
  • +
  • + up +
  • +
+

+
+
+
From patchwork Wed Nov 25 09:59:39 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 1405968 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.137; helo=fraxinus.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=cdW5daWf; dkim-atps=neutral Received: from fraxinus.osuosl.org (smtp4.osuosl.org [140.211.166.137]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4CgxFv1YCRz9s0b for ; Wed, 25 Nov 2020 21:00:02 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by fraxinus.osuosl.org (Postfix) with ESMTP id 64BB086B59; Wed, 25 Nov 2020 10:00:00 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from fraxinus.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id iSOn1BdyZTY6; Wed, 25 Nov 2020 09:59:59 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by fraxinus.osuosl.org (Postfix) with ESMTP id B127986B47; Wed, 25 Nov 2020 09:59:59 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 92242C163C; Wed, 25 Nov 2020 09:59:59 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from fraxinus.osuosl.org (smtp4.osuosl.org [140.211.166.137]) by lists.linuxfoundation.org (Postfix) with ESMTP id 28DA7C0052 for ; Wed, 25 Nov 2020 09:59:58 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by fraxinus.osuosl.org (Postfix) with ESMTP id 102F286B4E for ; Wed, 25 Nov 2020 09:59:58 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from fraxinus.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 4nfmT3mLJyCD for ; Wed, 25 Nov 2020 09:59:57 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [63.128.21.124]) by fraxinus.osuosl.org (Postfix) with ESMTPS id 4CE0586B47 for ; Wed, 25 Nov 2020 09:59:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1606298396; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=emFKd+iH92UHJX2z6t1vRSBOZmv9DiJE8o2hoj4AoK8=; b=cdW5daWfoi2OYds1ZJ5ahbr2c4A4l8VMOnhyHKpJekOjsuS5OBIwB9vCzcU9HKp1gezV3z 1lo4KR8dzRe/Ibsm75AnjyT15ahjWgClslm3GeYAE1gmqJ3AaqrfSXYWl+AhPGVDuZt2HS 0kcFZS08+mvGe7arKHQg3SeTMmHPAcc= Received: from mail-ej1-f70.google.com (mail-ej1-f70.google.com [209.85.218.70]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-58-pRc3QRW7ODqZUiFv1gp_6A-1; Wed, 25 Nov 2020 04:59:54 -0500 X-MC-Unique: pRc3QRW7ODqZUiFv1gp_6A-1 Received: by mail-ej1-f70.google.com with SMTP id gr9so633983ejb.19 for ; Wed, 25 Nov 2020 01:59:54 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=emFKd+iH92UHJX2z6t1vRSBOZmv9DiJE8o2hoj4AoK8=; b=EcyFidLq+8825HawBckjRIhWw4SiEK3MFdhwDuI33LgpyifDjsoxOsGgqeEdd4geem 0j0pqsubLQ4YBmDNk32IxU5EwRuRSmtpBxcG0/Q8N4ul+RkUwH+dIY+DHu7udFUz7nCX 9EGsesy68d9r4YsVQqtew743+TgoS0/Z/hMgZznF1OmLk/N7c8ld/6D3cSFtdk4gfTXd /sI1V9v8Pvr2662e5TslUGqakd/3VUCjGOiqVTw2gHmFreIHCxx90p/qdd2zqHNCDXH9 a8TPL1oG+AzgDSUbUsp9iSCovp+nKNbN24vzQS9srpA3J6qI5nrmwxr31hq3S9ulcKM9 xaFg== X-Gm-Message-State: AOAM531E5Hdb45/n8AhrBrndLg1xy+9Jx20cdtt/lkCOo9GrNHS5StVZ nkbGKfuYeYpRWIrLNHvNWF75BO53XTnBw3qo239XONnFCDuiLTQi2HEgLpx9n4rPB8Z/TclGx6l oH2MocKbGvu0SmaBITVtVsRZlkaHQRKJmHoeRl6PNs2t9luIvzaK7hZyJKTPrxO+YYpgXY6rP5q I= X-Received: by 2002:a17:906:9414:: with SMTP id q20mr2427280ejx.384.1606298392801; Wed, 25 Nov 2020 01:59:52 -0800 (PST) X-Google-Smtp-Source: ABdhPJwe8nFOVJE8ot8f4aURDI1ycARyX51ZxhW650/XxTSi/6oa1cUBbFESI0Mdjaxsk6OYwxdYgg== X-Received: by 2002:a17:906:9414:: with SMTP id q20mr2427255ejx.384.1606298392468; Wed, 25 Nov 2020 01:59:52 -0800 (PST) Received: from lore-desk.redhat.com ([151.66.8.153]) by smtp.gmail.com with ESMTPSA id g13sm936862edy.7.2020.11.25.01.59.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 25 Nov 2020 01:59:52 -0800 (PST) From: Lorenzo Bianconi To: dev@openvswitch.org Date: Wed, 25 Nov 2020 10:59:39 +0100 Message-Id: <4260786c2cb543827d8958a85d82f53b9dfd50d1.1606298055.git.lorenzo.bianconi@redhat.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: References: MIME-Version: 1.0 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=lorenzo.bianconi@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Cc: trozet@redhat.com Subject: [ovs-dev] [PATCH ovn 2/4] action: introduce handle_bfd_msg() action X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" Add handle_bfd_msg action to parse BFD packets received by the controller Signed-off-by: Lorenzo Bianconi --- controller/pinctrl.c | 17 +++++++++++++++++ include/ovn/actions.h | 7 +++++++ lib/actions.c | 16 ++++++++++++++++ tests/ovn.at | 4 ++++ utilities/ovn-trace.c | 2 ++ 5 files changed, 46 insertions(+) diff --git a/controller/pinctrl.c b/controller/pinctrl.c index 0e80c00c1..e7b9e90ce 100644 --- a/controller/pinctrl.c +++ b/controller/pinctrl.c @@ -329,6 +329,10 @@ static void bfd_monitor_init(void); static void bfd_monitor_destroy(void); static void bfd_monitor_send_msg(struct rconn *swconn, long long int *bfd_time) OVS_REQUIRES(pinctrl_mutex); +static void +pinctrl_handle_bfd_msg(struct rconn *swconn, const struct flow *ip_flow, + struct dp_packet *pkt_in, const struct match *md) + OVS_REQUIRES(pinctrl_mutex); static void bfd_monitor_run(const struct sbrec_bfd_table *bfd_table, struct ovsdb_idl_index *sbrec_port_binding_by_name, const struct sbrec_chassis *chassis, @@ -2975,6 +2979,12 @@ process_packet_in(struct rconn *swconn, const struct ofp_header *msg) ovs_mutex_unlock(&pinctrl_mutex); break; + case ACTION_OPCODE_BFD_MSG: + ovs_mutex_lock(&pinctrl_mutex); + pinctrl_handle_bfd_msg(swconn, &headers, &packet, &pin.flow_metadata); + ovs_mutex_unlock(&pinctrl_mutex); + break; + default: VLOG_WARN_RL(&rl, "unrecognized packet-in opcode %"PRIu32, ntohl(ah->opcode)); @@ -6487,6 +6497,13 @@ next: } } +static void +pinctrl_handle_bfd_msg(struct rconn *swconn, const struct flow *ip_flow, + struct dp_packet *pkt_in, const struct match *md) + OVS_REQUIRES(pinctrl_mutex) +{ +} + #define BFD_MONITOR_STALE_TIMEOUT 180000LL static void bfd_monitor_run(const struct sbrec_bfd_table *bfd_table, diff --git a/include/ovn/actions.h b/include/ovn/actions.h index 9c1ebf4aa..d104d4d64 100644 --- a/include/ovn/actions.h +++ b/include/ovn/actions.h @@ -105,6 +105,7 @@ struct ovn_extend_table; OVNACT(CHK_LB_HAIRPIN, ovnact_result) \ OVNACT(CHK_LB_HAIRPIN_REPLY, ovnact_result) \ OVNACT(CT_SNAT_TO_VIP, ovnact_null) \ + OVNACT(BFD_MSG, ovnact_null) \ /* enum ovnact_type, with a member OVNACT_ for each action. */ enum OVS_PACKED_ENUM ovnact_type { @@ -627,6 +628,12 @@ enum action_opcode { * The actions, in OpenFlow 1.3 format, follow the action_header. */ ACTION_OPCODE_REJECT, + + /* handle_bfd_msg { ...actions ...}." + * + * The actions, in OpenFlow 1.3 format, follow the action_header. + */ + ACTION_OPCODE_BFD_MSG, }; /* Header. */ diff --git a/lib/actions.c b/lib/actions.c index 0705e4ef3..8516f5d74 100644 --- a/lib/actions.c +++ b/lib/actions.c @@ -2740,6 +2740,20 @@ encode_DHCP6_REPLY(const struct ovnact_null *a OVS_UNUSED, encode_controller_op(ACTION_OPCODE_DHCP6_SERVER, ofpacts); } +static void +format_BFD_MSG(const struct ovnact_null *a OVS_UNUSED, struct ds *s) +{ + ds_put_cstr(s, "handle_bfd_msg;"); +} + +static void +encode_BFD_MSG(const struct ovnact_null *a OVS_UNUSED, + const struct ovnact_encode_params *ep OVS_UNUSED, + struct ofpbuf *ofpacts) +{ + encode_controller_op(ACTION_OPCODE_BFD_MSG, ofpacts); +} + static void parse_SET_QUEUE(struct action_context *ctx) { @@ -3840,6 +3854,8 @@ parse_action(struct action_context *ctx) parse_fwd_group_action(ctx); } else if (lexer_match_id(ctx->lexer, "handle_dhcpv6_reply")) { ovnact_put_DHCP6_REPLY(ctx->ovnacts); + } else if (lexer_match_id(ctx->lexer, "handle_bfd_msg")) { + ovnact_put_BFD_MSG(ctx->ovnacts); } else if (lexer_match_id(ctx->lexer, "reject")) { parse_REJECT(ctx); } else if (lexer_match_id(ctx->lexer, "ct_snat_to_vip")) { diff --git a/tests/ovn.at b/tests/ovn.at index 5b7a64cde..78a1b6443 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -1807,6 +1807,10 @@ ct_snat_to_vip; ct_snat_to_vip(foo); Syntax error at `(' expecting `;'. +# bfd packets +handle_bfd_msg; + encodes as controller(userdata=00.00.00.17.00.00.00.00) + # Miscellaneous negative tests. ; Syntax error at `;'. diff --git a/utilities/ovn-trace.c b/utilities/ovn-trace.c index 8eb7263b3..6d571476c 100644 --- a/utilities/ovn-trace.c +++ b/utilities/ovn-trace.c @@ -2520,6 +2520,8 @@ trace_actions(const struct ovnact *ovnacts, size_t ovnacts_len, break; case OVNACT_DHCP6_REPLY: break; + case OVNACT_BFD_MSG: + break; } } ds_destroy(&s); From patchwork Wed Nov 25 09:59:40 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 1405971 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.133; helo=hemlock.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=B71GYGfz; dkim-atps=neutral Received: from hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4CgxG855DZz9sSf for ; Wed, 25 Nov 2020 21:00:16 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by hemlock.osuosl.org (Postfix) with ESMTP id 4AE088753B; Wed, 25 Nov 2020 10:00:15 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from hemlock.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 1oct4xsAt4HX; Wed, 25 Nov 2020 10:00:13 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by hemlock.osuosl.org (Postfix) with ESMTP id D92888755F; Wed, 25 Nov 2020 10:00:13 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id BFE61C163C; Wed, 25 Nov 2020 10:00:13 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133]) by lists.linuxfoundation.org (Postfix) with ESMTP id 637B5C1836 for ; Wed, 25 Nov 2020 10:00:12 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by hemlock.osuosl.org (Postfix) with ESMTP id 48CA78755B for ; Wed, 25 Nov 2020 10:00:12 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from hemlock.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id SpdngvhkTKJi for ; Wed, 25 Nov 2020 10:00:08 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [63.128.21.124]) by hemlock.osuosl.org (Postfix) with ESMTPS id 8357F8754D for ; Wed, 25 Nov 2020 10:00:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1606298407; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=D9nzJA1KFMKQFrPF/mIoRQwPpe6RGxEUg85GuS1tOn4=; b=B71GYGfzlsL7Ru2HqH1yOgbdcH03VjSqnCi4wVooXmdOrSJLkxS47WSOaSxfoCqXS5Tzh5 iMEUB55QMUfK2C5POqZsu/uXb5KDdKGNHMHyyXPk8ToW1Q6eiLN6dLAREPVMZbafoCtr9d MjeED3Gtf5DcFXTsLByhUDEzXDVq2Fg= Received: from mail-ed1-f70.google.com (mail-ed1-f70.google.com [209.85.208.70]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-596-onBfn9aNPPWKwlW86n2q3g-1; Wed, 25 Nov 2020 04:59:56 -0500 X-MC-Unique: onBfn9aNPPWKwlW86n2q3g-1 Received: by mail-ed1-f70.google.com with SMTP id dj19so834425edb.13 for ; Wed, 25 Nov 2020 01:59:55 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=D9nzJA1KFMKQFrPF/mIoRQwPpe6RGxEUg85GuS1tOn4=; b=TcShTdDp4/3USsMa3V/QwMXEc2zvzkkeO/6MLFGx0eHCqxEBVKBHThyV2xNzGcUe54 BKCYwFsWwi2UknejU3VsbuhFV0OlGlMnwGwGHgD8T6wIj1Cxrox30P+3fxHkxJoq1Ijf 9gAaWUm4dHg/33Rb4L2vdmTYauIoQXqv0JZhnt0GcuM3mKk0s/1AkjTZpZjZPc/P86mk 7oqVFyKAaxyLu7H9bu8ujpKWRE0XBWRZOrs2LeVAwRgduAsOFgQ8RtI5HrrbymuzJjox aOETJTQQ2KqUxpCvFgCCnrbQKRE9d5TKdP/7Y/7qIuu2aZPgLj7M8yHUQ7rq/EGFudD6 8SUA== X-Gm-Message-State: AOAM530ReSQKrTrkpzKZZ9XslXfdTySCFUGnSzoKgt8UzLfI7cQ9bLfU 96jtgk5i5lZXvB4W4CB0+S04aGbVv20gYXD/KznXMuVJGAoY6ijNxSXuFWYHHiR5biWskjQeNe0 GInFXxgMGVf2zKRGnDlMfp3zBOdIJG87SDxJC4lLEboQQqkY+wUq1j+SWw3wnAX+sTcOPah3k0j o= X-Received: by 2002:a17:906:4dd4:: with SMTP id f20mr2425552ejw.94.1606298394095; Wed, 25 Nov 2020 01:59:54 -0800 (PST) X-Google-Smtp-Source: ABdhPJyqugTTS5nG2UAxftCw4L9cra29r1w0Wz6lgnhYV2aoRZ0sTT/vwifMDkDSv6ViuW7UkgrEqA== X-Received: by 2002:a17:906:4dd4:: with SMTP id f20mr2425524ejw.94.1606298393659; Wed, 25 Nov 2020 01:59:53 -0800 (PST) Received: from lore-desk.redhat.com ([151.66.8.153]) by smtp.gmail.com with ESMTPSA id g13sm936862edy.7.2020.11.25.01.59.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 25 Nov 2020 01:59:53 -0800 (PST) From: Lorenzo Bianconi To: dev@openvswitch.org Date: Wed, 25 Nov 2020 10:59:40 +0100 Message-Id: X-Mailer: git-send-email 2.28.0 In-Reply-To: References: MIME-Version: 1.0 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=lorenzo.bianconi@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Cc: trozet@redhat.com Subject: [ovs-dev] [PATCH ovn 3/4] controller: bfd: introduce BFD state machine X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" Introduce BFD state machine according to RFC880 https://tools.ietf.org/html/rfc5880 Introduce BFD logical flows in ovn-northd Signed-off-by: Lorenzo Bianconi --- controller/pinctrl.c | 275 +++++++++++++++++++++++++++++++++++++++- northd/ovn-northd.8.xml | 21 +++ northd/ovn-northd.c | 84 ++++++++++-- tests/atlocal.in | 3 + tests/system-ovn.at | 106 ++++++++++++++++ 5 files changed, 477 insertions(+), 12 deletions(-) diff --git a/controller/pinctrl.c b/controller/pinctrl.c index e7b9e90ce..c46a19ca2 100644 --- a/controller/pinctrl.c +++ b/controller/pinctrl.c @@ -6335,8 +6335,48 @@ sync_svc_monitors(struct ovsdb_idl_txn *ovnsb_idl_txn, } +enum bfd_state { + BFD_STATE_ADMIN_DOWN, + BFD_STATE_DOWN, + BFD_STATE_INIT, + BFD_STATE_UP, +}; + +enum bfd_flags { + BFD_FLAG_MULTIPOINT = 1 << 0, + BFD_FLAG_DEMAND = 1 << 1, + BFD_FLAG_AUTH = 1 << 2, + BFD_FLAG_CTL = 1 << 3, + BFD_FLAG_FINAL = 1 << 4, + BFD_FLAG_POLL = 1 << 5 +}; + +#define BFD_FLAGS_MASK 0x3f + +static char * +bfd_get_status(enum bfd_state state) +{ + switch (state) { + case BFD_STATE_ADMIN_DOWN: + return "admin_down"; + case BFD_STATE_DOWN: + return "down"; + case BFD_STATE_INIT: + return "init"; + case BFD_STATE_UP: + return "up"; + default: + return ""; + } +} + static struct hmap bfd_monitor_map; +#define BFD_UPDATE_BATCH_TH 10 +static uint16_t bpd_pending_update; +#define BFD_UPDATE_TIMEOUT 5000LL +static long long bfd_last_update; + struct bfd_entry { struct hmap_node node; @@ -6354,12 +6394,24 @@ struct bfd_entry { * sessions on the system */ uint16_t udp_src; - ovs_be32 disc; + ovs_be32 local_disc; + ovs_be32 remote_disc; + + uint32_t local_min_tx; + uint32_t local_min_rx; + uint32_t remote_min_rx; + + uint8_t local_mult; int64_t port_key; int64_t metadata; + enum bfd_state state; + bool change_state; + + uint32_t detection_timeout; long long int last_update; + long long int last_rx; long long int next_tx; }; @@ -6367,6 +6419,7 @@ static void bfd_monitor_init(void) { hmap_init(&bfd_monitor_map); + bfd_last_update = time_msec(); } static void @@ -6388,6 +6441,24 @@ pinctrl_find_bfd_monitor_entry_by_port(char *ip, uint16_t port) return NULL; } +static struct bfd_entry * +pinctrl_find_bfd_monitor_entry_by_disc(ovs_be32 ip, ovs_be32 disc) +{ + char *ip_src = xasprintf(IP_FMT, IP_ARGS(ip)); + struct bfd_entry *ret = NULL, *entry; + + HMAP_FOR_EACH_WITH_HASH (entry, node, hash_string(ip_src, 0), + &bfd_monitor_map) { + if (entry->local_disc == disc) { + ret = entry; + break; + } + } + + free(ip_src); + return ret; +} + static bool bfd_monitor_should_inject(void) { @@ -6438,9 +6509,36 @@ bfd_monitor_put_bfd_msg(struct bfd_entry *entry, struct dp_packet *packet) udp->udp_dst = htons(BFD_DEST_PORT); udp->udp_len = htons(sizeof *udp + sizeof *msg); - msg = dp_packet_put_uninit(packet, sizeof *msg); + msg = dp_packet_put_zeros(packet, sizeof *msg); msg->vers_diag = (BFD_VERSION << 5); + msg->mult = entry->local_mult; msg->length = BFD_PACKET_LEN; + msg->flags = entry->state << 6; + msg->my_disc = entry->local_disc; + msg->your_disc = entry->remote_disc; + msg->min_tx = htonl(entry->local_min_tx * 1000); + msg->min_rx = htonl(entry->local_min_rx * 1000); +} + +static bool +bpf_monitor_need_update(void) +{ + long long int cur_time = time_msec(); + + if (bpd_pending_update == BFD_UPDATE_BATCH_TH) { + goto update; + } + + if (bpd_pending_update && + bfd_last_update + BFD_UPDATE_TIMEOUT < cur_time) { + goto update; + } + return false; + +update: + bfd_last_update = cur_time; + bpd_pending_update = 0; + return true; } static void @@ -6450,11 +6548,28 @@ bfd_monitor_send_msg(struct rconn *swconn, long long int *bfd_time) long long int cur_time = time_msec(); struct bfd_entry *entry; + if (bpf_monitor_need_update()) { + notify_pinctrl_main(); + } + HMAP_FOR_EACH (entry, node, &bfd_monitor_map) { + if (cur_time > entry->last_rx + entry->detection_timeout && + entry->state != BFD_STATE_ADMIN_DOWN) { + entry->state = BFD_STATE_DOWN; + entry->change_state = true; + bfd_last_update = cur_time; + bpd_pending_update = 0; + notify_pinctrl_main(); + } + if (cur_time < entry->next_tx) { goto next; } + if (!entry->remote_min_rx) { + goto next; + } + uint64_t packet_stub[256 / 8]; struct dp_packet packet; dp_packet_use_stub(&packet, packet_stub, sizeof packet_stub); @@ -6489,7 +6604,10 @@ bfd_monitor_send_msg(struct rconn *swconn, long long int *bfd_time) dp_packet_uninit(&packet); ofpbuf_uninit(&ofpacts); - entry->next_tx = cur_time + 5000; + unsigned long tx_timeout = MAX(entry->local_min_tx, + entry->remote_min_rx); + tx_timeout -= random_range((tx_timeout * 25) / 100); + entry->next_tx = cur_time + tx_timeout; next: if (*bfd_time > entry->next_tx) { *bfd_time = entry->next_tx; @@ -6497,11 +6615,140 @@ next: } } +static bool +pinctrl_check_bfd_msg(const struct flow *ip_flow, struct dp_packet *pkt_in) +{ + if (ip_flow->dl_type != htons(ETH_TYPE_IP) && + ip_flow->dl_type != htons(ETH_TYPE_IPV6)) { + return false; + } + + if (ip_flow->nw_proto != IPPROTO_UDP) { + return false; + } + + struct udp_header *udp_hdr = dp_packet_l4(pkt_in); + if (udp_hdr->udp_dst != htons(BFD_DEST_PORT)) { + return false; + } + + const struct bfd_msg *msg = dp_packet_get_udp_payload(pkt_in); + uint8_t version = msg->vers_diag >> 5; + if (version != BFD_VERSION) { + return false; + } + + enum bfd_flags flags = msg->flags & BFD_FLAGS_MASK; + if (flags & BFD_FLAG_AUTH) { + /* AUTH not supported yet */ + return false; + } + + if (msg->length < BFD_PACKET_LEN) { + return false; + } + + if (!msg->mult) { + return false; + } + + if (flags & BFD_FLAG_MULTIPOINT) { + return false; + } + + if (!msg->my_disc) { + return false; + } + + enum bfd_state peer_state = msg->flags >> 6; + if (peer_state >= BFD_STATE_INIT && !msg->your_disc) { + return false; + } + + return true; +} + static void pinctrl_handle_bfd_msg(struct rconn *swconn, const struct flow *ip_flow, struct dp_packet *pkt_in, const struct match *md) OVS_REQUIRES(pinctrl_mutex) { + if (!pinctrl_check_bfd_msg(ip_flow, pkt_in)) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); + VLOG_WARN_RL(&rl, "BFD packet discarded"); + return; + } + + const struct bfd_msg *msg = dp_packet_get_udp_payload(pkt_in); + struct bfd_entry *entry = pinctrl_find_bfd_monitor_entry_by_disc( + ip_flow->nw_src, msg->your_disc); + if (!entry) { + return; + } + + bool change_state = false; + entry->remote_disc = msg->my_disc; + uint32_t remote_min_tx = ntohl(msg->min_tx) / 1000; + entry->remote_min_rx = ntohl(msg->min_rx) / 1000; + entry->detection_timeout = msg->mult * MAX(remote_min_tx, + entry->local_min_rx); + + enum bfd_state peer_state = msg->flags >> 6; + if (peer_state == BFD_STATE_ADMIN_DOWN && + entry->state >= BFD_STATE_INIT) { + entry->state = BFD_STATE_DOWN; + entry->last_rx = time_msec(); + change_state = true; + goto out; + } + + /* bfd state machine */ + switch (entry->state) { + case BFD_STATE_DOWN: + if (peer_state == BFD_STATE_DOWN) { + entry->state = BFD_STATE_INIT; + change_state = true; + } + if (peer_state == BFD_STATE_INIT) { + entry->state = BFD_STATE_UP; + change_state = true; + } + entry->last_rx = time_msec(); + break; + case BFD_STATE_INIT: + if (peer_state == BFD_STATE_INIT || + peer_state == BFD_STATE_UP) { + entry->state = BFD_STATE_UP; + change_state = true; + } + if (peer_state == BFD_STATE_ADMIN_DOWN) { + entry->state = BFD_STATE_DOWN; + change_state = true; + } + entry->last_rx = time_msec(); + break; + case BFD_STATE_UP: + if (peer_state == BFD_STATE_ADMIN_DOWN || + peer_state == BFD_STATE_DOWN) { + entry->state = BFD_STATE_DOWN; + change_state = true; + } + entry->last_rx = time_msec(); + break; + case BFD_STATE_ADMIN_DOWN: + default: + break; + } + +out: + /* let's try to bacth db updates */ + if (change_state) { + entry->change_state = true; + bpd_pending_update++; + } + if (bpf_monitor_need_update()) { + notify_pinctrl_main(); + } } #define BFD_MONITOR_STALE_TIMEOUT 180000LL @@ -6581,14 +6828,34 @@ bfd_monitor_run(const struct sbrec_bfd_table *bfd_table, entry->ip_src = ip_src; entry->ip_dst = ip_dst; entry->udp_src = bt->src_port; - entry->disc = htonl(bt->disc); + entry->local_disc = htonl(bt->disc); entry->next_tx = cur_time; + entry->last_rx = cur_time; + entry->detection_timeout = 30000; entry->metadata = pb->datapath->tunnel_key; entry->port_key = pb->tunnel_key; + entry->state = BFD_STATE_DOWN; + entry->local_min_tx = bt->min_tx; + entry->local_min_rx = bt->min_rx; + entry->remote_min_rx = bt->min_rx; + entry->local_mult = bt->detect_mult; uint32_t hash = hash_string(bt->dst_ip, 0); hmap_insert(&bfd_monitor_map, &entry->node, hash); changed = true; + } else if (!strcmp(bt->status, "admin_down") && + entry->state != BFD_STATE_ADMIN_DOWN) { + entry->state = BFD_STATE_ADMIN_DOWN; + entry->change_state = false; + changed = true; + } else if (strcmp(bt->status, "admin_down") && + entry->state == BFD_STATE_ADMIN_DOWN) { + entry->state = BFD_STATE_DOWN; + entry->change_state = false; + changed = true; + } else if (entry->change_state) { + sbrec_bfd_set_status(bt, bfd_get_status(entry->state)); + entry->change_state = false; } entry->last_update = cur_time; } diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml index 294402de3..58f2ba100 100644 --- a/northd/ovn-northd.8.xml +++ b/northd/ovn-northd.8.xml @@ -1926,6 +1926,27 @@ next;

+
  • +

    + For each BFD port the two following priorirty-110 flows are added + to manage BFD traffic: + +

      +
    • + if ip4.src or ip6.src is any IP + address owned by the router port and udp.dst == 3784 + , the packet is advanced to the next pipeline stage. +
    • + +
    • + if ip4.dst or ip6.dst is any IP + address owned by the router port and udp.dst == 3784 + , the handle_bfd_msg action is executed. +
    • +
    +

    +
  • +
  • L3 admission control: A priority-100 flow drops packets that match diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c index d25f370ae..91e408dc6 100644 --- a/northd/ovn-northd.c +++ b/northd/ovn-northd.c @@ -1467,6 +1467,8 @@ struct ovn_port { bool has_unknown; /* If the addresses have 'unknown' defined. */ + bool has_bfd; + /* The port's peer: * * - A switch port S of type "router" has a router port R as a peer, @@ -8032,16 +8034,15 @@ add_route(struct hmap *lflows, const struct ovn_port *op, build_route_match(op_inport, network_s, plen, is_src_route, is_ipv4, &match, &priority); - struct ds actions = DS_EMPTY_INITIALIZER; - ds_put_format(&actions, "ip.ttl--; "REG_ECMP_GROUP_ID" = 0; %s = ", + struct ds common_actions = DS_EMPTY_INITIALIZER; + ds_put_format(&common_actions, REG_ECMP_GROUP_ID" = 0; %s = ", is_ipv4 ? REG_NEXT_HOP_IPV4 : REG_NEXT_HOP_IPV6); - if (gateway) { - ds_put_cstr(&actions, gateway); + ds_put_cstr(&common_actions, gateway); } else { - ds_put_format(&actions, "ip%s.dst", is_ipv4 ? "4" : "6"); + ds_put_format(&common_actions, "ip%s.dst", is_ipv4 ? "4" : "6"); } - ds_put_format(&actions, "; " + ds_put_format(&common_actions, "; " "%s = %s; " "eth.src = %s; " "outport = %s; " @@ -8051,11 +8052,20 @@ add_route(struct hmap *lflows, const struct ovn_port *op, lrp_addr_s, op->lrp_networks.ea_s, op->json_key); + struct ds actions = DS_EMPTY_INITIALIZER; + ds_put_format(&actions, "ip.ttl--; %s", ds_cstr(&common_actions)); ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_ROUTING, priority, ds_cstr(&match), ds_cstr(&actions), stage_hint); + if (op->has_bfd) { + ds_put_format(&match, " && udp.dst == 3784"); + ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_ROUTING, + priority + 1, ds_cstr(&match), + ds_cstr(&common_actions), stage_hint); + } ds_destroy(&match); + ds_destroy(&common_actions); ds_destroy(&actions); } @@ -8717,6 +8727,52 @@ build_lrouter_force_snat_flows(struct hmap *lflows, struct ovn_datapath *od, ds_destroy(&actions); } +static void +build_lrouter_bfd_flows(struct hmap *lflows, struct ovn_port *op) +{ + if (!op->has_bfd) { + return; + } + + struct ds ip_list = DS_EMPTY_INITIALIZER; + struct ds match = DS_EMPTY_INITIALIZER; + + if (op->lrp_networks.n_ipv4_addrs) { + op_put_v4_networks(&ip_list, op, false); + ds_put_format(&match, "ip4.src == %s && udp.dst == 3784", + ds_cstr(&ip_list)); + ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_INPUT, 110, + ds_cstr(&match), "next; ", + &op->nbrp->header_); + ds_clear(&match); + ds_put_format(&match, "ip4.dst == %s && udp.dst == 3784", + ds_cstr(&ip_list)); + ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_INPUT, 110, + ds_cstr(&match), "handle_bfd_msg; ", + &op->nbrp->header_); + } + if (op->lrp_networks.n_ipv6_addrs) { + ds_clear(&ip_list); + ds_clear(&match); + + op_put_v6_networks(&ip_list, op); + ds_put_format(&match, "ip6.src == %s && udp.dst == 3784", + ds_cstr(&ip_list)); + ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_INPUT, 110, + ds_cstr(&match), "next; ", + &op->nbrp->header_); + ds_clear(&match); + ds_put_format(&match, "ip6.dst == %s && udp.dst == 3784", + ds_cstr(&ip_list)); + ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_INPUT, 110, + ds_cstr(&match), "handle_bfd_msg; ", + &op->nbrp->header_); + } + + ds_destroy(&ip_list); + ds_destroy(&match); +} + static void build_lrouter_flows(struct hmap *datapaths, struct hmap *ports, struct hmap *lflows, struct shash *meter_groups, @@ -8821,6 +8877,9 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports, &op->nbrp->header_); } + /* BFD msg handling */ + build_lrouter_bfd_flows(lflows, op); + /* ICMP time exceeded */ for (int i = 0; i < op->lrp_networks.n_ipv4_addrs; i++) { ds_clear(&match); @@ -11357,7 +11416,7 @@ struct bfd_entry { }; static void -build_bfd_table(struct northd_context *ctx) +build_bfd_table(struct northd_context *ctx, struct hmap *ports) { const struct nbrec_nb_global *nb = nbrec_nb_global_first(ctx->ovnnb_idl); @@ -11417,10 +11476,18 @@ build_bfd_table(struct northd_context *ctx) break; } } + struct ovn_port *op = ovn_port_find(ports, nb_bt->logical_port); + if (op) { + op->has_bfd = true; + } } HMAP_FOR_EACH_SAFE (bfd_e, next_bfd_e, hmap_node, &sb_only) { if (!bfd_e->found && bfd_e->sb_bt) { + struct ovn_port *op = ovn_port_find(ports, bfd_e->logical_port); + if (op) { + op->has_bfd = false; + } sbrec_bfd_delete(bfd_e->sb_bt); } free(bfd_e->logical_port); @@ -12214,6 +12281,7 @@ ovnnb_db_run(struct northd_context *ctx, controller_event_en = smap_get_bool(&nb->options, "controller_event", false); + bfd_en = smap_get_bool(&nb->options, "bfd", false); check_lsp_is_up = !smap_get_bool(&nb->options, "ignore_lsp_down", false); @@ -12226,7 +12294,7 @@ ovnnb_db_run(struct northd_context *ctx, build_ip_mcast(ctx, datapaths); build_mcast_groups(ctx, datapaths, ports, &mcast_groups, &igmp_groups); build_meter_groups(ctx, &meter_groups); - build_bfd_table(ctx); + build_bfd_table(ctx, ports); build_lflows(ctx, datapaths, ports, &port_groups, &mcast_groups, &igmp_groups, &meter_groups, &lbs); ovn_update_ipv6_prefix(ports); diff --git a/tests/atlocal.in b/tests/atlocal.in index 4517ebf72..0ee18149e 100644 --- a/tests/atlocal.in +++ b/tests/atlocal.in @@ -181,6 +181,9 @@ fi # Set HAVE_DIBBLER-SERVER find_command dibbler-server +# Set HAVE_BFDD_BEACON +find_command bfdd-beacon + # Turn off proxies. unset http_proxy unset https_proxy diff --git a/tests/system-ovn.at b/tests/system-ovn.at index d59f7c97e..a53b3d264 100644 --- a/tests/system-ovn.at +++ b/tests/system-ovn.at @@ -5505,3 +5505,109 @@ as OVS_TRAFFIC_VSWITCHD_STOP(["/.*error receiving.*/d /.*terminating with signal 15.*/d"]) AT_CLEANUP + +AT_SETUP([ovn -- BFD]) +AT_SKIP_IF([test $HAVE_BFDD_BEACON = no]) +AT_KEYWORDS([ovn-bfd]) + +ovn_start +OVS_TRAFFIC_VSWITCHD_START() + +ADD_BR([br-int]) +ADD_BR([br-ext]) + +ovs-ofctl add-flow br-ext action=normal +# Set external-ids in br-int needed for ovn-controller +ovs-vsctl \ + -- set Open_vSwitch . external-ids:system-id=hv1 \ + -- set Open_vSwitch . external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \ + -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \ + -- set Open_vSwitch . external-ids:ovn-encap-ip=169.0.0.1 \ + -- set bridge br-int fail-mode=secure other-config:disable-in-band=true + +# Start ovn-controller +start_daemon ovn-controller + +ovn-nbctl lr-add R1 + +ovn-nbctl ls-add sw0 +ovn-nbctl ls-add sw1 +ovn-nbctl ls-add public + +ovn-nbctl lrp-add R1 rp-sw0 00:00:01:01:02:03 192.168.1.1/24 +ovn-nbctl lrp-add R1 rp-sw1 00:00:03:01:02:03 192.168.2.1/24 +ovn-nbctl lrp-add R1 rp-public 00:00:02:01:02:03 172.16.1.1/24 \ + -- lrp-set-gateway-chassis rp-public hv1 + +ovn-nbctl lsp-add sw0 sw0-rp -- set Logical_Switch_Port sw0-rp \ + type=router options:router-port=rp-sw0 \ + -- lsp-set-addresses sw0-rp router +ovn-nbctl lsp-add sw1 sw1-rp -- set Logical_Switch_Port sw1-rp \ + type=router options:router-port=rp-sw1 \ + -- lsp-set-addresses sw1-rp router + +ovn-nbctl lsp-add public public-rp -- set Logical_Switch_Port public-rp \ + type=router options:router-port=rp-public \ + -- lsp-set-addresses public-rp router + +ADD_NAMESPACES(sw01) +ADD_VETH(sw01, sw01, br-int, "192.168.1.2/24", "f0:00:00:01:02:03", \ + "192.168.1.1") +ovn-nbctl lsp-add sw0 sw01 \ + -- lsp-set-addresses sw01 "f0:00:00:01:02:03 192.168.1.2" + +ADD_NAMESPACES(sw11) +ADD_VETH(sw11, sw11, br-int, "192.168.2.2/24", "f0:00:00:02:02:03", \ + "192.168.2.1") +ovn-nbctl lsp-add sw1 sw11 \ + -- lsp-set-addresses sw11 "f0:00:00:02:02:03 192.168.2.2" + +ADD_NAMESPACES(server) +NS_CHECK_EXEC([server], [ip link set dev lo up]) +ADD_VETH(s1, server, br-ext, "172.16.1.50/24", "f0:00:00:01:02:05", \ + "172.16.1.1") + +AT_CHECK([ovs-vsctl set Open_vSwitch . external-ids:ovn-bridge-mappings=phynet:br-ext]) +ovn-nbctl lsp-add public public1 \ + -- lsp-set-addresses public1 unknown \ + -- lsp-set-type public1 localnet \ + -- lsp-set-options public1 network_name=phynet + +NS_CHECK_EXEC([server], [bfdd-beacon --listen=172.16.1.50], [0]) +NS_CHECK_EXEC([server], [bfdd-control allow 172.16.1.1], [0], [dnl +Allowing connections from 172.16.1.1 +]) + +ovn-nbctl create bfd logical_port=rp-public dst_ip=172.16.1.50 status=down min_tx=250 min_rx=250 detect_mult=10 +ovn-nbctl set NB_Global . options:bfd=true +ovn-nbctl --wait=hv sync + +OVS_WAIT_UNTIL([test "$(ovn-nbctl list bfd | awk -F: '/status/{print substr($2,2)}')" = "up"]) +AT_CHECK([ovn-nbctl list bfd | awk -F: '/status/{print substr($2,2)}'], [0], [dnl +up +]) + +NS_CHECK_EXEC([server], [bfdd-control stop], [0], [dnl +stopping +]) + +OVS_WAIT_UNTIL([test "$(ovn-nbctl list bfd | awk -F: '/status/{print substr($2,2)}')" = "down"]) +AT_CHECK([ovn-nbctl list bfd | awk -F: '/status/{print substr($2,2)}'], [0], [dnl +down +]) + +kill $(pidof ovn-controller) + +as ovn-sb +OVS_APP_EXIT_AND_WAIT([ovsdb-server]) + +as ovn-nb +OVS_APP_EXIT_AND_WAIT([ovsdb-server]) + +as northd +OVS_APP_EXIT_AND_WAIT([ovn-northd]) + +as +OVS_TRAFFIC_VSWITCHD_STOP(["/.*error receiving.*/d +/.*terminating with signal 15.*/d"]) +AT_CLEANUP From patchwork Wed Nov 25 09:59:41 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 1405972 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.137; helo=fraxinus.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=OhNxWTRS; dkim-atps=neutral Received: from fraxinus.osuosl.org (smtp4.osuosl.org [140.211.166.137]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4CgxGG5H7Xz9sSf for ; Wed, 25 Nov 2020 21:00:22 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by fraxinus.osuosl.org (Postfix) with ESMTP id 4DA7786C3E; Wed, 25 Nov 2020 10:00:21 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from fraxinus.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 7D645Iksd-42; Wed, 25 Nov 2020 10:00:18 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by fraxinus.osuosl.org (Postfix) with ESMTP id 166A786BFE; Wed, 25 Nov 2020 10:00:15 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id EB78BC0052; Wed, 25 Nov 2020 10:00:14 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from fraxinus.osuosl.org (smtp4.osuosl.org [140.211.166.137]) by lists.linuxfoundation.org (Postfix) with ESMTP id C17F9C0052 for ; Wed, 25 Nov 2020 10:00:12 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by fraxinus.osuosl.org (Postfix) with ESMTP id 9454686BA5 for ; Wed, 25 Nov 2020 10:00:12 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from fraxinus.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id AejVA12ZPz1L for ; Wed, 25 Nov 2020 10:00:11 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [216.205.24.124]) by fraxinus.osuosl.org (Postfix) with ESMTPS id A441186BA8 for ; Wed, 25 Nov 2020 10:00:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1606298410; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=RJ7BrNPtm0qzga3v80+/hG8ZlCTsd8dbnqnlLdora7E=; b=OhNxWTRS6OIV/h5r2h/Xmq0Rvp3FsA6yOgNbHXqvV4hoRKPEC2/3RhWzAZj6YsmGZx5zID Xs54qy2WnhMOD/aiZMVhNasHKYgx5M65cRWebLboUjQHO1ghV10bClqh9HFRDI7+4OYSLa Hf93GBmdKjDpTTB8+gzUG2XXIOTQrp0= Received: from mail-ed1-f71.google.com (mail-ed1-f71.google.com [209.85.208.71]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-211-nveJMLtBM6WO3X6HLXfsCw-1; Wed, 25 Nov 2020 04:59:56 -0500 X-MC-Unique: nveJMLtBM6WO3X6HLXfsCw-1 Received: by mail-ed1-f71.google.com with SMTP id b68so840043edf.9 for ; Wed, 25 Nov 2020 01:59:56 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=RJ7BrNPtm0qzga3v80+/hG8ZlCTsd8dbnqnlLdora7E=; b=DwHFxZF+gEral2aZ5PLP3vNNep1TsKE6qQ/PKoj4LZmTw1IyyXHWr+S87MwvpyedBi gpJdBz9zxRp/OTm//3MXprPpflmEJMQaFCIc8iumgeZ5Ttu8WIi8kelztLN0MIaWYhAI TpbbhocoRbZCcR6YrOKcyw9Quw7cPthRGynGnbaKRzVAHtV/yoLCMNuTWPZB7L0wd+Qu QmXqOgvn6/FwiDt8WJUUpRPbj0ApsqFHgwD8WiBMbSJkRdH7oSA57dTHOUy5yegDtmB+ GPq74MuXdSiaJoMhFpfvPXLCoDjKC2X2mVsXCYViKJCVXG4tP8AGdOClpEVkc9P6UWEu LtvA== X-Gm-Message-State: AOAM531ecdkxLygLKV6d19njAQgMgzZ5qM/2Kz4vrI110DaYvbHITmpp HRL0qVUgoEy9G2BtqkO8Nb/+ucN/whnkHoX5PDWVa6kYJyXgsldbKxQr4zzpBy6EfKhcauWUNQG HKKPtxkrMZFCdYPBNlkJd66zF32aWnC8GiQHfMfWvGZEvKCTQDKF7U62UOf4eNptO2qCfDfcPbK s= X-Received: by 2002:a17:906:d784:: with SMTP id pj4mr2402758ejb.78.1606298395114; Wed, 25 Nov 2020 01:59:55 -0800 (PST) X-Google-Smtp-Source: ABdhPJzMh8T3V7ZqETHY+k5LTLmELjs7txPiJKpOuttkSZIAhsbY4n0OX2nqK+8RxWGoAVI/f3QRTg== X-Received: by 2002:a17:906:d784:: with SMTP id pj4mr2402749ejb.78.1606298394812; Wed, 25 Nov 2020 01:59:54 -0800 (PST) Received: from lore-desk.redhat.com ([151.66.8.153]) by smtp.gmail.com with ESMTPSA id g13sm936862edy.7.2020.11.25.01.59.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 25 Nov 2020 01:59:54 -0800 (PST) From: Lorenzo Bianconi To: dev@openvswitch.org Date: Wed, 25 Nov 2020 10:59:41 +0100 Message-Id: X-Mailer: git-send-email 2.28.0 In-Reply-To: References: MIME-Version: 1.0 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=lorenzo.bianconi@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Cc: trozet@redhat.com Subject: [ovs-dev] [PATCH ovn 4/4] bfp: support demand mode on rx side X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" Introduce rx demand mode support according to RFC5880 [0]. Demand mode on tx side is not supported yet https://tools.ietf.org/html/rfc5880 Signed-off-by: Lorenzo Bianconi --- controller/pinctrl.c | 104 +++++++++++++++++++++++++++---------------- 1 file changed, 66 insertions(+), 38 deletions(-) diff --git a/controller/pinctrl.c b/controller/pinctrl.c index c46a19ca2..89b632058 100644 --- a/controller/pinctrl.c +++ b/controller/pinctrl.c @@ -331,7 +331,7 @@ static void bfd_monitor_send_msg(struct rconn *swconn, long long int *bfd_time) OVS_REQUIRES(pinctrl_mutex); static void pinctrl_handle_bfd_msg(struct rconn *swconn, const struct flow *ip_flow, - struct dp_packet *pkt_in, const struct match *md) + struct dp_packet *pkt_in) OVS_REQUIRES(pinctrl_mutex); static void bfd_monitor_run(const struct sbrec_bfd_table *bfd_table, struct ovsdb_idl_index *sbrec_port_binding_by_name, @@ -2981,7 +2981,7 @@ process_packet_in(struct rconn *swconn, const struct ofp_header *msg) case ACTION_OPCODE_BFD_MSG: ovs_mutex_lock(&pinctrl_mutex); - pinctrl_handle_bfd_msg(swconn, &headers, &packet, &pin.flow_metadata); + pinctrl_handle_bfd_msg(swconn, &headers, &packet); ovs_mutex_unlock(&pinctrl_mutex); break; @@ -6401,6 +6401,8 @@ struct bfd_entry { uint32_t local_min_rx; uint32_t remote_min_rx; + bool remote_demand_mode; + uint8_t local_mult; int64_t port_key; @@ -6482,7 +6484,8 @@ bfd_monitor_wait(long long int timeout) } static void -bfd_monitor_put_bfd_msg(struct bfd_entry *entry, struct dp_packet *packet) +bfd_monitor_put_bfd_msg(struct bfd_entry *entry, struct dp_packet *packet, + bool final) { struct udp_header *udp; struct bfd_msg *msg; @@ -6513,13 +6516,54 @@ bfd_monitor_put_bfd_msg(struct bfd_entry *entry, struct dp_packet *packet) msg->vers_diag = (BFD_VERSION << 5); msg->mult = entry->local_mult; msg->length = BFD_PACKET_LEN; - msg->flags = entry->state << 6; + msg->flags = final ? BFD_FLAG_FINAL : 0; + msg->flags |= entry->state << 6; msg->my_disc = entry->local_disc; msg->your_disc = entry->remote_disc; msg->min_tx = htonl(entry->local_min_tx * 1000); msg->min_rx = htonl(entry->local_min_rx * 1000); } +static void +pinctrl_send_bfd_tx_msg(struct rconn *swconn, struct bfd_entry *entry, + bool final) +{ + uint64_t packet_stub[256 / 8]; + struct dp_packet packet; + dp_packet_use_stub(&packet, packet_stub, sizeof packet_stub); + bfd_monitor_put_bfd_msg(entry, &packet, final); + + uint64_t ofpacts_stub[4096 / 8]; + struct ofpbuf ofpacts = OFPBUF_STUB_INITIALIZER(ofpacts_stub); + + /* Set MFF_LOG_DATAPATH and MFF_LOG_INPORT. */ + uint32_t dp_key = entry->metadata; + uint32_t port_key = entry->port_key; + put_load(dp_key, MFF_LOG_DATAPATH, 0, 64, &ofpacts); + put_load(port_key, MFF_LOG_INPORT, 0, 32, &ofpacts); + put_load(1, MFF_LOG_FLAGS, MLF_LOCAL_ONLY_BIT, 1, &ofpacts); + struct ofpact_resubmit *resubmit = ofpact_put_RESUBMIT(&ofpacts); + resubmit->in_port = OFPP_CONTROLLER; + resubmit->table_id = OFTABLE_LOG_INGRESS_PIPELINE; + + struct ofputil_packet_out po = { + .packet = dp_packet_data(&packet), + .packet_len = dp_packet_size(&packet), + .buffer_id = UINT32_MAX, + .ofpacts = ofpacts.data, + .ofpacts_len = ofpacts.size, + }; + + match_set_in_port(&po.flow_metadata, OFPP_CONTROLLER); + enum ofp_version version = rconn_get_version(swconn); + enum ofputil_protocol proto = + ofputil_protocol_from_ofp_version(version); + queue_msg(swconn, ofputil_encode_packet_out(&po, proto)); + dp_packet_uninit(&packet); + ofpbuf_uninit(&ofpacts); +} + + static bool bpf_monitor_need_update(void) { @@ -6570,40 +6614,11 @@ bfd_monitor_send_msg(struct rconn *swconn, long long int *bfd_time) goto next; } - uint64_t packet_stub[256 / 8]; - struct dp_packet packet; - dp_packet_use_stub(&packet, packet_stub, sizeof packet_stub); - bfd_monitor_put_bfd_msg(entry, &packet); - - uint64_t ofpacts_stub[4096 / 8]; - struct ofpbuf ofpacts = OFPBUF_STUB_INITIALIZER(ofpacts_stub); - - /* Set MFF_LOG_DATAPATH and MFF_LOG_INPORT. */ - uint32_t dp_key = entry->metadata; - uint32_t port_key = entry->port_key; - put_load(dp_key, MFF_LOG_DATAPATH, 0, 64, &ofpacts); - put_load(port_key, MFF_LOG_INPORT, 0, 32, &ofpacts); - put_load(1, MFF_LOG_FLAGS, MLF_LOCAL_ONLY_BIT, 1, &ofpacts); - struct ofpact_resubmit *resubmit = ofpact_put_RESUBMIT(&ofpacts); - resubmit->in_port = OFPP_CONTROLLER; - resubmit->table_id = OFTABLE_LOG_INGRESS_PIPELINE; - - struct ofputil_packet_out po = { - .packet = dp_packet_data(&packet), - .packet_len = dp_packet_size(&packet), - .buffer_id = UINT32_MAX, - .ofpacts = ofpacts.data, - .ofpacts_len = ofpacts.size, - }; - - match_set_in_port(&po.flow_metadata, OFPP_CONTROLLER); - enum ofp_version version = rconn_get_version(swconn); - enum ofputil_protocol proto = - ofputil_protocol_from_ofp_version(version); - queue_msg(swconn, ofputil_encode_packet_out(&po, proto)); - dp_packet_uninit(&packet); - ofpbuf_uninit(&ofpacts); + if (entry->remote_demand_mode) { + goto next; + } + pinctrl_send_bfd_tx_msg(swconn, entry, false); unsigned long tx_timeout = MAX(entry->local_min_tx, entry->remote_min_rx); tx_timeout -= random_range((tx_timeout * 25) / 100); @@ -6660,6 +6675,10 @@ pinctrl_check_bfd_msg(const struct flow *ip_flow, struct dp_packet *pkt_in) return false; } + if ((flags & BFD_FLAG_FINAL) && (flags & BFD_FLAG_POLL)) { + return false; + } + enum bfd_state peer_state = msg->flags >> 6; if (peer_state >= BFD_STATE_INIT && !msg->your_disc) { return false; @@ -6670,7 +6689,7 @@ pinctrl_check_bfd_msg(const struct flow *ip_flow, struct dp_packet *pkt_in) static void pinctrl_handle_bfd_msg(struct rconn *swconn, const struct flow *ip_flow, - struct dp_packet *pkt_in, const struct match *md) + struct dp_packet *pkt_in) OVS_REQUIRES(pinctrl_mutex) { if (!pinctrl_check_bfd_msg(ip_flow, pkt_in)) { @@ -6740,6 +6759,15 @@ pinctrl_handle_bfd_msg(struct rconn *swconn, const struct flow *ip_flow, break; } + if (entry->state == BFD_STATE_UP && + (msg->flags & BFD_FLAG_DEMAND)) { + entry->remote_demand_mode = true; + } + + if (msg->flags & BFD_FLAG_POLL) { + pinctrl_send_bfd_tx_msg(swconn, entry, true); + } + out: /* let's try to bacth db updates */ if (change_state) {