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) {