|
|
5f9769 |
From e75d53c69261a0b104c75d8f6f7dc7175a690833 Mon Sep 17 00:00:00 2001
|
|
|
5f9769 |
Message-Id: <e75d53c69261a0b104c75d8f6f7dc7175a690833.1610458802.git.lorenzo.bianconi@redhat.com>
|
|
|
5f9769 |
In-Reply-To: <f21c1b7a467a691847b5552d4570af706fcc5bb0.1610458802.git.lorenzo.bianconi@redhat.com>
|
|
|
5f9769 |
References: <f21c1b7a467a691847b5552d4570af706fcc5bb0.1610458802.git.lorenzo.bianconi@redhat.com>
|
|
|
5f9769 |
From: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>
|
|
|
5f9769 |
Date: Fri, 8 Jan 2021 17:36:22 +0100
|
|
|
5f9769 |
Subject: [PATCH 14/16] controller: bfd: introduce BFD state machine.
|
|
|
5f9769 |
|
|
|
5f9769 |
Introduce BFD state machine for BFD packet parsing
|
|
|
5f9769 |
according to RFC880 https://tools.ietf.org/html/rfc5880.
|
|
|
5f9769 |
Introduce BFD logical flows in ovn-northd.
|
|
|
5f9769 |
|
|
|
5f9769 |
Change-Id: I1ea057ad45393360fa917eb6e3a576dd37cfbc0d
|
|
|
5f9769 |
Acked-by: Mark Michelson <mmichels@redhat.com>
|
|
|
5f9769 |
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>
|
|
|
5f9769 |
Signed-off-by: Numan Siddique <numans@ovn.org>
|
|
|
5f9769 |
---
|
|
|
5f9769 |
NEWS | 6 +
|
|
|
5f9769 |
controller/pinctrl.c | 342 ++++++++++++++++++++++++++++++++++++++--
|
|
|
5f9769 |
northd/ovn-northd.8.xml | 21 +++
|
|
|
5f9769 |
northd/ovn-northd.c | 85 +++++++++-
|
|
|
5f9769 |
tests/ovn-northd.at | 55 +++++++
|
|
|
5f9769 |
5 files changed, 488 insertions(+), 21 deletions(-)
|
|
|
5f9769 |
|
|
|
5f9769 |
diff --git a/NEWS b/NEWS
|
|
|
5f9769 |
index f71ec329c..85f63503e 100644
|
|
|
5f9769 |
--- a/NEWS
|
|
|
5f9769 |
+++ b/NEWS
|
|
|
5f9769 |
@@ -1,3 +1,9 @@
|
|
|
5f9769 |
+Post-v20.12.0
|
|
|
5f9769 |
+-------------------------
|
|
|
5f9769 |
+ - Support ECMP multiple nexthops for reroute router policies.
|
|
|
5f9769 |
+ - BFD protocol support according to RFC880 [0]. IPv6 is not suported yet.
|
|
|
5f9769 |
+ [0] https://tools.ietf.org/html/rfc5880)
|
|
|
5f9769 |
+
|
|
|
5f9769 |
OVN v20.12.0 - 18 Dec 2020
|
|
|
5f9769 |
--------------------------
|
|
|
5f9769 |
- The "datapath" argument to ovn-trace is now optional, since the
|
|
|
5f9769 |
diff --git a/controller/pinctrl.c b/controller/pinctrl.c
|
|
|
5f9769 |
index deeae7479..6e363a0f9 100644
|
|
|
5f9769 |
--- a/controller/pinctrl.c
|
|
|
5f9769 |
+++ b/controller/pinctrl.c
|
|
|
5f9769 |
@@ -330,9 +330,10 @@ static void bfd_monitor_destroy(void);
|
|
|
5f9769 |
static void bfd_monitor_send_msg(struct rconn *swconn, long long int *bfd_time)
|
|
|
5f9769 |
OVS_REQUIRES(pinctrl_mutex);
|
|
|
5f9769 |
static void
|
|
|
5f9769 |
-pinctrl_handle_bfd_msg(void)
|
|
|
5f9769 |
+pinctrl_handle_bfd_msg(const struct flow *ip_flow, struct dp_packet *pkt_in)
|
|
|
5f9769 |
OVS_REQUIRES(pinctrl_mutex);
|
|
|
5f9769 |
-static void bfd_monitor_run(const struct sbrec_bfd_table *bfd_table,
|
|
|
5f9769 |
+static void bfd_monitor_run(struct ovsdb_idl_txn *ovnsb_idl_txn,
|
|
|
5f9769 |
+ const struct sbrec_bfd_table *bfd_table,
|
|
|
5f9769 |
struct ovsdb_idl_index *sbrec_port_binding_by_name,
|
|
|
5f9769 |
const struct sbrec_chassis *chassis,
|
|
|
5f9769 |
const struct sset *active_tunnels)
|
|
|
5f9769 |
@@ -2980,7 +2981,7 @@ process_packet_in(struct rconn *swconn, const struct ofp_header *msg)
|
|
|
5f9769 |
|
|
|
5f9769 |
case ACTION_OPCODE_BFD_MSG:
|
|
|
5f9769 |
ovs_mutex_lock(&pinctrl_mutex);
|
|
|
5f9769 |
- pinctrl_handle_bfd_msg();
|
|
|
5f9769 |
+ pinctrl_handle_bfd_msg(&headers, &packet);
|
|
|
5f9769 |
ovs_mutex_unlock(&pinctrl_mutex);
|
|
|
5f9769 |
break;
|
|
|
5f9769 |
|
|
|
5f9769 |
@@ -3206,10 +3207,8 @@ pinctrl_run(struct ovsdb_idl_txn *ovnsb_idl_txn,
|
|
|
5f9769 |
local_datapaths);
|
|
|
5f9769 |
sync_svc_monitors(ovnsb_idl_txn, svc_mon_table, sbrec_port_binding_by_name,
|
|
|
5f9769 |
chassis);
|
|
|
5f9769 |
- if (ovnsb_idl_txn) {
|
|
|
5f9769 |
- bfd_monitor_run(bfd_table, sbrec_port_binding_by_name, chassis,
|
|
|
5f9769 |
- active_tunnels);
|
|
|
5f9769 |
- }
|
|
|
5f9769 |
+ bfd_monitor_run(ovnsb_idl_txn, bfd_table, sbrec_port_binding_by_name,
|
|
|
5f9769 |
+ chassis, active_tunnels);
|
|
|
5f9769 |
ovs_mutex_unlock(&pinctrl_mutex);
|
|
|
5f9769 |
}
|
|
|
5f9769 |
|
|
|
5f9769 |
@@ -6345,8 +6344,48 @@ sync_svc_monitors(struct ovsdb_idl_txn *ovnsb_idl_txn,
|
|
|
5f9769 |
|
|
|
5f9769 |
}
|
|
|
5f9769 |
|
|
|
5f9769 |
+enum bfd_state {
|
|
|
5f9769 |
+ BFD_STATE_ADMIN_DOWN,
|
|
|
5f9769 |
+ BFD_STATE_DOWN,
|
|
|
5f9769 |
+ BFD_STATE_INIT,
|
|
|
5f9769 |
+ BFD_STATE_UP,
|
|
|
5f9769 |
+};
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+enum bfd_flags {
|
|
|
5f9769 |
+ BFD_FLAG_MULTIPOINT = 1 << 0,
|
|
|
5f9769 |
+ BFD_FLAG_DEMAND = 1 << 1,
|
|
|
5f9769 |
+ BFD_FLAG_AUTH = 1 << 2,
|
|
|
5f9769 |
+ BFD_FLAG_CTL = 1 << 3,
|
|
|
5f9769 |
+ BFD_FLAG_FINAL = 1 << 4,
|
|
|
5f9769 |
+ BFD_FLAG_POLL = 1 << 5
|
|
|
5f9769 |
+};
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+#define BFD_FLAGS_MASK 0x3f
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+static char *
|
|
|
5f9769 |
+bfd_get_status(enum bfd_state state)
|
|
|
5f9769 |
+{
|
|
|
5f9769 |
+ switch (state) {
|
|
|
5f9769 |
+ case BFD_STATE_ADMIN_DOWN:
|
|
|
5f9769 |
+ return "admin_down";
|
|
|
5f9769 |
+ case BFD_STATE_DOWN:
|
|
|
5f9769 |
+ return "down";
|
|
|
5f9769 |
+ case BFD_STATE_INIT:
|
|
|
5f9769 |
+ return "init";
|
|
|
5f9769 |
+ case BFD_STATE_UP:
|
|
|
5f9769 |
+ return "up";
|
|
|
5f9769 |
+ default:
|
|
|
5f9769 |
+ return "";
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+}
|
|
|
5f9769 |
+
|
|
|
5f9769 |
static struct hmap bfd_monitor_map;
|
|
|
5f9769 |
|
|
|
5f9769 |
+#define BFD_UPDATE_BATCH_TH 10
|
|
|
5f9769 |
+static uint16_t bfd_pending_update;
|
|
|
5f9769 |
+#define BFD_UPDATE_TIMEOUT 5000LL
|
|
|
5f9769 |
+static long long bfd_last_update;
|
|
|
5f9769 |
+
|
|
|
5f9769 |
struct bfd_entry {
|
|
|
5f9769 |
struct hmap_node node;
|
|
|
5f9769 |
bool erase;
|
|
|
5f9769 |
@@ -6365,11 +6404,23 @@ struct bfd_entry {
|
|
|
5f9769 |
* sessions on the system
|
|
|
5f9769 |
*/
|
|
|
5f9769 |
uint16_t udp_src;
|
|
|
5f9769 |
- ovs_be32 disc;
|
|
|
5f9769 |
+ ovs_be32 local_disc;
|
|
|
5f9769 |
+ ovs_be32 remote_disc;
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ uint32_t local_min_tx;
|
|
|
5f9769 |
+ uint32_t local_min_rx;
|
|
|
5f9769 |
+ uint32_t remote_min_rx;
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ uint8_t local_mult;
|
|
|
5f9769 |
|
|
|
5f9769 |
int64_t port_key;
|
|
|
5f9769 |
int64_t metadata;
|
|
|
5f9769 |
|
|
|
5f9769 |
+ enum bfd_state state;
|
|
|
5f9769 |
+ bool change_state;
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ uint32_t detection_timeout;
|
|
|
5f9769 |
+ long long int last_rx;
|
|
|
5f9769 |
long long int next_tx;
|
|
|
5f9769 |
};
|
|
|
5f9769 |
|
|
|
5f9769 |
@@ -6377,6 +6428,7 @@ static void
|
|
|
5f9769 |
bfd_monitor_init(void)
|
|
|
5f9769 |
{
|
|
|
5f9769 |
hmap_init(&bfd_monitor_map);
|
|
|
5f9769 |
+ bfd_last_update = time_msec();
|
|
|
5f9769 |
}
|
|
|
5f9769 |
|
|
|
5f9769 |
static void
|
|
|
5f9769 |
@@ -6402,6 +6454,24 @@ pinctrl_find_bfd_monitor_entry_by_port(char *ip, uint16_t port)
|
|
|
5f9769 |
return NULL;
|
|
|
5f9769 |
}
|
|
|
5f9769 |
|
|
|
5f9769 |
+static struct bfd_entry *
|
|
|
5f9769 |
+pinctrl_find_bfd_monitor_entry_by_disc(ovs_be32 ip, ovs_be32 disc)
|
|
|
5f9769 |
+{
|
|
|
5f9769 |
+ char *ip_src = xasprintf(IP_FMT, IP_ARGS(ip));
|
|
|
5f9769 |
+ struct bfd_entry *ret = NULL, *entry;
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ HMAP_FOR_EACH_WITH_HASH (entry, node, hash_string(ip_src, 0),
|
|
|
5f9769 |
+ &bfd_monitor_map) {
|
|
|
5f9769 |
+ if (entry->local_disc == disc) {
|
|
|
5f9769 |
+ ret = entry;
|
|
|
5f9769 |
+ break;
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ free(ip_src);
|
|
|
5f9769 |
+ return ret;
|
|
|
5f9769 |
+}
|
|
|
5f9769 |
+
|
|
|
5f9769 |
static bool
|
|
|
5f9769 |
bfd_monitor_should_inject(void)
|
|
|
5f9769 |
{
|
|
|
5f9769 |
@@ -6453,9 +6523,60 @@ bfd_monitor_put_bfd_msg(struct bfd_entry *entry, struct dp_packet *packet)
|
|
|
5f9769 |
udp->udp_dst = htons(BFD_DEST_PORT);
|
|
|
5f9769 |
udp->udp_len = htons(sizeof *udp + sizeof *msg);
|
|
|
5f9769 |
|
|
|
5f9769 |
- msg = dp_packet_put_uninit(packet, sizeof *msg);
|
|
|
5f9769 |
+ msg = dp_packet_put_zeros(packet, sizeof *msg);
|
|
|
5f9769 |
msg->vers_diag = (BFD_VERSION << 5);
|
|
|
5f9769 |
+ msg->mult = entry->local_mult;
|
|
|
5f9769 |
msg->length = BFD_PACKET_LEN;
|
|
|
5f9769 |
+ msg->flags = entry->state << 6;
|
|
|
5f9769 |
+ msg->my_disc = entry->local_disc;
|
|
|
5f9769 |
+ msg->your_disc = entry->remote_disc;
|
|
|
5f9769 |
+ /* min_tx and min_rx are in us - RFC 5880 page 9 */
|
|
|
5f9769 |
+ msg->min_tx = htonl(entry->local_min_tx * 1000);
|
|
|
5f9769 |
+ msg->min_rx = htonl(entry->local_min_rx * 1000);
|
|
|
5f9769 |
+}
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+static bool
|
|
|
5f9769 |
+bfd_monitor_need_update(void)
|
|
|
5f9769 |
+{
|
|
|
5f9769 |
+ long long int cur_time = time_msec();
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ if (bfd_pending_update == BFD_UPDATE_BATCH_TH) {
|
|
|
5f9769 |
+ goto update;
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ if (bfd_pending_update &&
|
|
|
5f9769 |
+ bfd_last_update + BFD_UPDATE_TIMEOUT < cur_time) {
|
|
|
5f9769 |
+ goto update;
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+ return false;
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+update:
|
|
|
5f9769 |
+ bfd_last_update = cur_time;
|
|
|
5f9769 |
+ bfd_pending_update = 0;
|
|
|
5f9769 |
+ return true;
|
|
|
5f9769 |
+}
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+static void
|
|
|
5f9769 |
+bfd_check_detection_timeout(struct bfd_entry *entry)
|
|
|
5f9769 |
+{
|
|
|
5f9769 |
+ if (entry->state == BFD_STATE_ADMIN_DOWN) {
|
|
|
5f9769 |
+ return;
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ if (!entry->detection_timeout) {
|
|
|
5f9769 |
+ return;
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ long long int cur_time = time_msec();
|
|
|
5f9769 |
+ if (cur_time < entry->last_rx + entry->detection_timeout) {
|
|
|
5f9769 |
+ return;
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ entry->state = BFD_STATE_DOWN;
|
|
|
5f9769 |
+ entry->change_state = true;
|
|
|
5f9769 |
+ bfd_last_update = cur_time;
|
|
|
5f9769 |
+ bfd_pending_update = 0;
|
|
|
5f9769 |
+ notify_pinctrl_main();
|
|
|
5f9769 |
}
|
|
|
5f9769 |
|
|
|
5f9769 |
static void
|
|
|
5f9769 |
@@ -6465,11 +6586,27 @@ bfd_monitor_send_msg(struct rconn *swconn, long long int *bfd_time)
|
|
|
5f9769 |
long long int cur_time = time_msec();
|
|
|
5f9769 |
struct bfd_entry *entry;
|
|
|
5f9769 |
|
|
|
5f9769 |
+ if (bfd_monitor_need_update()) {
|
|
|
5f9769 |
+ notify_pinctrl_main();
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+
|
|
|
5f9769 |
HMAP_FOR_EACH (entry, node, &bfd_monitor_map) {
|
|
|
5f9769 |
+ unsigned long tx_timeout;
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ bfd_check_detection_timeout(entry);
|
|
|
5f9769 |
+
|
|
|
5f9769 |
if (cur_time < entry->next_tx) {
|
|
|
5f9769 |
goto next;
|
|
|
5f9769 |
}
|
|
|
5f9769 |
|
|
|
5f9769 |
+ if (!entry->remote_min_rx) {
|
|
|
5f9769 |
+ continue;
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ if (entry->state == BFD_STATE_ADMIN_DOWN) {
|
|
|
5f9769 |
+ continue;
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+
|
|
|
5f9769 |
uint64_t packet_stub[256 / 8];
|
|
|
5f9769 |
struct dp_packet packet;
|
|
|
5f9769 |
dp_packet_use_stub(&packet, packet_stub, sizeof packet_stub);
|
|
|
5f9769 |
@@ -6504,7 +6641,9 @@ bfd_monitor_send_msg(struct rconn *swconn, long long int *bfd_time)
|
|
|
5f9769 |
dp_packet_uninit(&packet);
|
|
|
5f9769 |
ofpbuf_uninit(&ofpacts);
|
|
|
5f9769 |
|
|
|
5f9769 |
- entry->next_tx = cur_time + 5000;
|
|
|
5f9769 |
+ tx_timeout = MAX(entry->local_min_tx, entry->remote_min_rx);
|
|
|
5f9769 |
+ tx_timeout -= random_range((tx_timeout * 25) / 100);
|
|
|
5f9769 |
+ entry->next_tx = cur_time + tx_timeout;
|
|
|
5f9769 |
next:
|
|
|
5f9769 |
if (*bfd_time > entry->next_tx) {
|
|
|
5f9769 |
*bfd_time = entry->next_tx;
|
|
|
5f9769 |
@@ -6512,14 +6651,167 @@ next:
|
|
|
5f9769 |
}
|
|
|
5f9769 |
}
|
|
|
5f9769 |
|
|
|
5f9769 |
+static bool
|
|
|
5f9769 |
+pinctrl_check_bfd_msg(const struct flow *ip_flow, struct dp_packet *pkt_in)
|
|
|
5f9769 |
+{
|
|
|
5f9769 |
+ if (ip_flow->dl_type != htons(ETH_TYPE_IP) &&
|
|
|
5f9769 |
+ ip_flow->dl_type != htons(ETH_TYPE_IPV6)) {
|
|
|
5f9769 |
+ return false;
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ if (ip_flow->nw_proto != IPPROTO_UDP) {
|
|
|
5f9769 |
+ return false;
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ struct udp_header *udp_hdr = dp_packet_l4(pkt_in);
|
|
|
5f9769 |
+ if (udp_hdr->udp_dst != htons(BFD_DEST_PORT)) {
|
|
|
5f9769 |
+ return false;
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ const struct bfd_msg *msg = dp_packet_get_udp_payload(pkt_in);
|
|
|
5f9769 |
+ uint8_t version = msg->vers_diag >> 5;
|
|
|
5f9769 |
+ if (version != BFD_VERSION) {
|
|
|
5f9769 |
+ return false;
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ enum bfd_flags flags = msg->flags & BFD_FLAGS_MASK;
|
|
|
5f9769 |
+ if (flags & BFD_FLAG_AUTH) {
|
|
|
5f9769 |
+ /* AUTH not supported yet */
|
|
|
5f9769 |
+ return false;
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ if (msg->length < BFD_PACKET_LEN) {
|
|
|
5f9769 |
+ return false;
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ if (!msg->mult) {
|
|
|
5f9769 |
+ return false;
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ if (flags & BFD_FLAG_MULTIPOINT) {
|
|
|
5f9769 |
+ return false;
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ if (!msg->my_disc) {
|
|
|
5f9769 |
+ return false;
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ enum bfd_state peer_state = msg->flags >> 6;
|
|
|
5f9769 |
+ if (peer_state >= BFD_STATE_INIT && !msg->your_disc) {
|
|
|
5f9769 |
+ return false;
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ return true;
|
|
|
5f9769 |
+}
|
|
|
5f9769 |
+
|
|
|
5f9769 |
static void
|
|
|
5f9769 |
-pinctrl_handle_bfd_msg(void)
|
|
|
5f9769 |
+pinctrl_handle_bfd_msg(const struct flow *ip_flow, struct dp_packet *pkt_in)
|
|
|
5f9769 |
OVS_REQUIRES(pinctrl_mutex)
|
|
|
5f9769 |
{
|
|
|
5f9769 |
+ if (!pinctrl_check_bfd_msg(ip_flow, pkt_in)) {
|
|
|
5f9769 |
+ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
|
|
|
5f9769 |
+ VLOG_WARN_RL(&rl, "BFD packet discarded");
|
|
|
5f9769 |
+ return;
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ const struct bfd_msg *msg = dp_packet_get_udp_payload(pkt_in);
|
|
|
5f9769 |
+ struct bfd_entry *entry = pinctrl_find_bfd_monitor_entry_by_disc(
|
|
|
5f9769 |
+ ip_flow->nw_src, msg->your_disc);
|
|
|
5f9769 |
+ if (!entry) {
|
|
|
5f9769 |
+ return;
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ bool change_state = false;
|
|
|
5f9769 |
+ entry->remote_disc = msg->my_disc;
|
|
|
5f9769 |
+ uint32_t remote_min_tx = ntohl(msg->min_tx) / 1000;
|
|
|
5f9769 |
+ entry->remote_min_rx = ntohl(msg->min_rx) / 1000;
|
|
|
5f9769 |
+ entry->detection_timeout = msg->mult * MAX(remote_min_tx,
|
|
|
5f9769 |
+ entry->local_min_rx);
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ enum bfd_state peer_state = msg->flags >> 6;
|
|
|
5f9769 |
+ if (peer_state == BFD_STATE_ADMIN_DOWN &&
|
|
|
5f9769 |
+ entry->state >= BFD_STATE_INIT) {
|
|
|
5f9769 |
+ entry->state = BFD_STATE_DOWN;
|
|
|
5f9769 |
+ entry->last_rx = time_msec();
|
|
|
5f9769 |
+ change_state = true;
|
|
|
5f9769 |
+ goto out;
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ /* bfd state machine */
|
|
|
5f9769 |
+ switch (entry->state) {
|
|
|
5f9769 |
+ case BFD_STATE_DOWN:
|
|
|
5f9769 |
+ if (peer_state == BFD_STATE_DOWN) {
|
|
|
5f9769 |
+ entry->state = BFD_STATE_INIT;
|
|
|
5f9769 |
+ change_state = true;
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+ if (peer_state == BFD_STATE_INIT) {
|
|
|
5f9769 |
+ entry->state = BFD_STATE_UP;
|
|
|
5f9769 |
+ change_state = true;
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+ entry->last_rx = time_msec();
|
|
|
5f9769 |
+ break;
|
|
|
5f9769 |
+ case BFD_STATE_INIT:
|
|
|
5f9769 |
+ if (peer_state == BFD_STATE_INIT ||
|
|
|
5f9769 |
+ peer_state == BFD_STATE_UP) {
|
|
|
5f9769 |
+ entry->state = BFD_STATE_UP;
|
|
|
5f9769 |
+ change_state = true;
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+ if (peer_state == BFD_STATE_ADMIN_DOWN) {
|
|
|
5f9769 |
+ entry->state = BFD_STATE_DOWN;
|
|
|
5f9769 |
+ change_state = true;
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+ entry->last_rx = time_msec();
|
|
|
5f9769 |
+ break;
|
|
|
5f9769 |
+ case BFD_STATE_UP:
|
|
|
5f9769 |
+ if (peer_state == BFD_STATE_ADMIN_DOWN ||
|
|
|
5f9769 |
+ peer_state == BFD_STATE_DOWN) {
|
|
|
5f9769 |
+ entry->state = BFD_STATE_DOWN;
|
|
|
5f9769 |
+ change_state = true;
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+ entry->last_rx = time_msec();
|
|
|
5f9769 |
+ break;
|
|
|
5f9769 |
+ case BFD_STATE_ADMIN_DOWN:
|
|
|
5f9769 |
+ default:
|
|
|
5f9769 |
+ break;
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+out:
|
|
|
5f9769 |
+ /* let's try to bacth db updates */
|
|
|
5f9769 |
+ if (change_state) {
|
|
|
5f9769 |
+ entry->change_state = true;
|
|
|
5f9769 |
+ bfd_pending_update++;
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+ if (bfd_monitor_need_update()) {
|
|
|
5f9769 |
+ notify_pinctrl_main();
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+}
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+static void
|
|
|
5f9769 |
+bfd_monitor_check_sb_conf(const struct sbrec_bfd *sb_bt,
|
|
|
5f9769 |
+ struct bfd_entry *entry)
|
|
|
5f9769 |
+{
|
|
|
5f9769 |
+ ovs_be32 ip_dst;
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ if (ip_parse(sb_bt->dst_ip, &ip_dst) && ip_dst != entry->ip_dst) {
|
|
|
5f9769 |
+ entry->ip_dst = ip_dst;
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ if (sb_bt->min_tx != entry->local_min_tx) {
|
|
|
5f9769 |
+ entry->local_min_tx = sb_bt->min_tx;
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ if (sb_bt->min_rx != entry->local_min_rx) {
|
|
|
5f9769 |
+ entry->local_min_rx = sb_bt->min_rx;
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ if (sb_bt->detect_mult != entry->local_mult) {
|
|
|
5f9769 |
+ entry->local_mult = sb_bt->detect_mult;
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
}
|
|
|
5f9769 |
|
|
|
5f9769 |
static void
|
|
|
5f9769 |
-bfd_monitor_run(const struct sbrec_bfd_table *bfd_table,
|
|
|
5f9769 |
+bfd_monitor_run(struct ovsdb_idl_txn *ovnsb_idl_txn,
|
|
|
5f9769 |
+ const struct sbrec_bfd_table *bfd_table,
|
|
|
5f9769 |
struct ovsdb_idl_index *sbrec_port_binding_by_name,
|
|
|
5f9769 |
const struct sbrec_chassis *chassis,
|
|
|
5f9769 |
const struct sset *active_tunnels)
|
|
|
5f9769 |
@@ -6599,15 +6891,39 @@ bfd_monitor_run(const struct sbrec_bfd_table *bfd_table,
|
|
|
5f9769 |
entry->ip_src = ip_src;
|
|
|
5f9769 |
entry->ip_dst = ip_dst;
|
|
|
5f9769 |
entry->udp_src = bt->src_port;
|
|
|
5f9769 |
- entry->disc = htonl(bt->disc);
|
|
|
5f9769 |
+ entry->local_disc = htonl(bt->disc);
|
|
|
5f9769 |
entry->next_tx = cur_time;
|
|
|
5f9769 |
+ entry->last_rx = cur_time;
|
|
|
5f9769 |
+ entry->detection_timeout = 30000;
|
|
|
5f9769 |
entry->metadata = pb->datapath->tunnel_key;
|
|
|
5f9769 |
entry->port_key = pb->tunnel_key;
|
|
|
5f9769 |
+ entry->state = BFD_STATE_ADMIN_DOWN;
|
|
|
5f9769 |
+ entry->local_min_tx = bt->min_tx;
|
|
|
5f9769 |
+ entry->local_min_rx = bt->min_rx;
|
|
|
5f9769 |
+ entry->remote_min_rx = 1; /* RFC5880 page 29 */
|
|
|
5f9769 |
+ entry->local_mult = bt->detect_mult;
|
|
|
5f9769 |
|
|
|
5f9769 |
uint32_t hash = hash_string(bt->dst_ip, 0);
|
|
|
5f9769 |
hmap_insert(&bfd_monitor_map, &entry->node, hash);
|
|
|
5f9769 |
+ } else if (!strcmp(bt->status, "admin_down") &&
|
|
|
5f9769 |
+ entry->state != BFD_STATE_ADMIN_DOWN) {
|
|
|
5f9769 |
+ entry->state = BFD_STATE_ADMIN_DOWN;
|
|
|
5f9769 |
+ entry->change_state = false;
|
|
|
5f9769 |
+ entry->remote_disc = 0;
|
|
|
5f9769 |
+ } else if (strcmp(bt->status, "admin_down") &&
|
|
|
5f9769 |
+ entry->state == BFD_STATE_ADMIN_DOWN) {
|
|
|
5f9769 |
+ entry->state = BFD_STATE_DOWN;
|
|
|
5f9769 |
+ entry->change_state = false;
|
|
|
5f9769 |
+ entry->remote_disc = 0;
|
|
|
5f9769 |
changed = true;
|
|
|
5f9769 |
+ } else if (entry->change_state && ovnsb_idl_txn) {
|
|
|
5f9769 |
+ if (entry->state == BFD_STATE_DOWN) {
|
|
|
5f9769 |
+ entry->remote_disc = 0;
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+ sbrec_bfd_set_status(bt, bfd_get_status(entry->state));
|
|
|
5f9769 |
+ entry->change_state = false;
|
|
|
5f9769 |
}
|
|
|
5f9769 |
+ bfd_monitor_check_sb_conf(bt, entry);
|
|
|
5f9769 |
entry->erase = false;
|
|
|
5f9769 |
}
|
|
|
5f9769 |
|
|
|
5f9769 |
diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml
|
|
|
5f9769 |
index 1f0f71f34..48c52a56a 100644
|
|
|
5f9769 |
--- a/northd/ovn-northd.8.xml
|
|
|
5f9769 |
+++ b/northd/ovn-northd.8.xml
|
|
|
5f9769 |
@@ -1936,6 +1936,27 @@ next;
|
|
|
5f9769 |
|
|
|
5f9769 |
|
|
|
5f9769 |
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ For each BFD port the two following priority-110 flows are added
|
|
|
5f9769 |
+ to manage BFD traffic:
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ if ip4.src or ip6.src is any IP
|
|
|
5f9769 |
+ address owned by the router port and udp.dst == 3784
|
|
|
5f9769 |
+ , the packet is advanced to the next pipeline stage.
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ if ip4.dst or ip6.dst is any IP
|
|
|
5f9769 |
+ address owned by the router port and udp.dst == 3784
|
|
|
5f9769 |
+ , the handle_bfd_msg action is executed.
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+
|
|
|
5f9769 |
|
|
|
5f9769 |
|
|
|
5f9769 |
L3 admission control: A priority-100 flow drops packets that match
|
|
|
5f9769 |
diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
|
|
|
5f9769 |
index 77ea2181c..363bb0895 100644
|
|
|
5f9769 |
--- a/northd/ovn-northd.c
|
|
|
5f9769 |
+++ b/northd/ovn-northd.c
|
|
|
5f9769 |
@@ -1473,6 +1473,8 @@ struct ovn_port {
|
|
|
5f9769 |
|
|
|
5f9769 |
bool has_unknown; /* If the addresses have 'unknown' defined. */
|
|
|
5f9769 |
|
|
|
5f9769 |
+ bool has_bfd;
|
|
|
5f9769 |
+
|
|
|
5f9769 |
/* The port's peer:
|
|
|
5f9769 |
*
|
|
|
5f9769 |
* - A switch port S of type "router" has a router port R as a peer,
|
|
|
5f9769 |
@@ -7597,7 +7599,8 @@ static int bfd_get_unused_port(unsigned long *bfd_src_ports)
|
|
|
5f9769 |
}
|
|
|
5f9769 |
|
|
|
5f9769 |
static void
|
|
|
5f9769 |
-build_bfd_table(struct northd_context *ctx, struct hmap *bfd_connections)
|
|
|
5f9769 |
+build_bfd_table(struct northd_context *ctx, struct hmap *bfd_connections,
|
|
|
5f9769 |
+ struct hmap *ports)
|
|
|
5f9769 |
{
|
|
|
5f9769 |
struct hmap sb_only = HMAP_INITIALIZER(&sb_only);
|
|
|
5f9769 |
const struct sbrec_bfd *sb_bt;
|
|
|
5f9769 |
@@ -7661,9 +7664,18 @@ build_bfd_table(struct northd_context *ctx, struct hmap *bfd_connections)
|
|
|
5f9769 |
hash = hash_string(bfd_e->sb_bt->logical_port, hash);
|
|
|
5f9769 |
hmap_insert(bfd_connections, &bfd_e->hmap_node, hash);
|
|
|
5f9769 |
}
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ struct ovn_port *op = ovn_port_find(ports, nb_bt->logical_port);
|
|
|
5f9769 |
+ if (op) {
|
|
|
5f9769 |
+ op->has_bfd = true;
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
}
|
|
|
5f9769 |
|
|
|
5f9769 |
HMAP_FOR_EACH_POP (bfd_e, hmap_node, &sb_only) {
|
|
|
5f9769 |
+ struct ovn_port *op = ovn_port_find(ports, bfd_e->sb_bt->logical_port);
|
|
|
5f9769 |
+ if (op) {
|
|
|
5f9769 |
+ op->has_bfd = false;
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
sbrec_bfd_delete(bfd_e->sb_bt);
|
|
|
5f9769 |
free(bfd_e);
|
|
|
5f9769 |
}
|
|
|
5f9769 |
@@ -8423,16 +8435,15 @@ add_route(struct hmap *lflows, const struct ovn_port *op,
|
|
|
5f9769 |
build_route_match(op_inport, network_s, plen, is_src_route, is_ipv4,
|
|
|
5f9769 |
&match, &priority);
|
|
|
5f9769 |
|
|
|
5f9769 |
- struct ds actions = DS_EMPTY_INITIALIZER;
|
|
|
5f9769 |
- ds_put_format(&actions, "ip.ttl--; "REG_ECMP_GROUP_ID" = 0; %s = ",
|
|
|
5f9769 |
+ struct ds common_actions = DS_EMPTY_INITIALIZER;
|
|
|
5f9769 |
+ ds_put_format(&common_actions, REG_ECMP_GROUP_ID" = 0; %s = ",
|
|
|
5f9769 |
is_ipv4 ? REG_NEXT_HOP_IPV4 : REG_NEXT_HOP_IPV6);
|
|
|
5f9769 |
-
|
|
|
5f9769 |
if (gateway) {
|
|
|
5f9769 |
- ds_put_cstr(&actions, gateway);
|
|
|
5f9769 |
+ ds_put_cstr(&common_actions, gateway);
|
|
|
5f9769 |
} else {
|
|
|
5f9769 |
- ds_put_format(&actions, "ip%s.dst", is_ipv4 ? "4" : "6");
|
|
|
5f9769 |
+ ds_put_format(&common_actions, "ip%s.dst", is_ipv4 ? "4" : "6");
|
|
|
5f9769 |
}
|
|
|
5f9769 |
- ds_put_format(&actions, "; "
|
|
|
5f9769 |
+ ds_put_format(&common_actions, "; "
|
|
|
5f9769 |
"%s = %s; "
|
|
|
5f9769 |
"eth.src = %s; "
|
|
|
5f9769 |
"outport = %s; "
|
|
|
5f9769 |
@@ -8442,11 +8453,20 @@ add_route(struct hmap *lflows, const struct ovn_port *op,
|
|
|
5f9769 |
lrp_addr_s,
|
|
|
5f9769 |
op->lrp_networks.ea_s,
|
|
|
5f9769 |
op->json_key);
|
|
|
5f9769 |
+ struct ds actions = DS_EMPTY_INITIALIZER;
|
|
|
5f9769 |
+ ds_put_format(&actions, "ip.ttl--; %s", ds_cstr(&common_actions));
|
|
|
5f9769 |
|
|
|
5f9769 |
ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_ROUTING, priority,
|
|
|
5f9769 |
ds_cstr(&match), ds_cstr(&actions),
|
|
|
5f9769 |
stage_hint);
|
|
|
5f9769 |
+ if (op->has_bfd) {
|
|
|
5f9769 |
+ ds_put_format(&match, " && udp.dst == 3784");
|
|
|
5f9769 |
+ ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_ROUTING,
|
|
|
5f9769 |
+ priority + 1, ds_cstr(&match),
|
|
|
5f9769 |
+ ds_cstr(&common_actions), stage_hint);
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
ds_destroy(&match);
|
|
|
5f9769 |
+ ds_destroy(&common_actions);
|
|
|
5f9769 |
ds_destroy(&actions);
|
|
|
5f9769 |
}
|
|
|
5f9769 |
|
|
|
5f9769 |
@@ -9108,6 +9128,52 @@ build_lrouter_force_snat_flows(struct hmap *lflows, struct ovn_datapath *od,
|
|
|
5f9769 |
ds_destroy(&actions);
|
|
|
5f9769 |
}
|
|
|
5f9769 |
|
|
|
5f9769 |
+static void
|
|
|
5f9769 |
+build_lrouter_bfd_flows(struct hmap *lflows, struct ovn_port *op)
|
|
|
5f9769 |
+{
|
|
|
5f9769 |
+ if (!op->has_bfd) {
|
|
|
5f9769 |
+ return;
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ struct ds ip_list = DS_EMPTY_INITIALIZER;
|
|
|
5f9769 |
+ struct ds match = DS_EMPTY_INITIALIZER;
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ if (op->lrp_networks.n_ipv4_addrs) {
|
|
|
5f9769 |
+ op_put_v4_networks(&ip_list, op, false);
|
|
|
5f9769 |
+ ds_put_format(&match, "ip4.src == %s && udp.dst == 3784",
|
|
|
5f9769 |
+ ds_cstr(&ip_list));
|
|
|
5f9769 |
+ ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_INPUT, 110,
|
|
|
5f9769 |
+ ds_cstr(&match), "next; ",
|
|
|
5f9769 |
+ &op->nbrp->header_);
|
|
|
5f9769 |
+ ds_clear(&match);
|
|
|
5f9769 |
+ ds_put_format(&match, "ip4.dst == %s && udp.dst == 3784",
|
|
|
5f9769 |
+ ds_cstr(&ip_list));
|
|
|
5f9769 |
+ ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_INPUT, 110,
|
|
|
5f9769 |
+ ds_cstr(&match), "handle_bfd_msg(); ",
|
|
|
5f9769 |
+ &op->nbrp->header_);
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+ if (op->lrp_networks.n_ipv6_addrs) {
|
|
|
5f9769 |
+ ds_clear(&ip_list);
|
|
|
5f9769 |
+ ds_clear(&match);
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ op_put_v6_networks(&ip_list, op);
|
|
|
5f9769 |
+ ds_put_format(&match, "ip6.src == %s && udp.dst == 3784",
|
|
|
5f9769 |
+ ds_cstr(&ip_list));
|
|
|
5f9769 |
+ ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_INPUT, 110,
|
|
|
5f9769 |
+ ds_cstr(&match), "next; ",
|
|
|
5f9769 |
+ &op->nbrp->header_);
|
|
|
5f9769 |
+ ds_clear(&match);
|
|
|
5f9769 |
+ ds_put_format(&match, "ip6.dst == %s && udp.dst == 3784",
|
|
|
5f9769 |
+ ds_cstr(&ip_list));
|
|
|
5f9769 |
+ ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_INPUT, 110,
|
|
|
5f9769 |
+ ds_cstr(&match), "handle_bfd_msg(); ",
|
|
|
5f9769 |
+ &op->nbrp->header_);
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ ds_destroy(&ip_list);
|
|
|
5f9769 |
+ ds_destroy(&match);
|
|
|
5f9769 |
+}
|
|
|
5f9769 |
+
|
|
|
5f9769 |
/* Logical router ingress Table 0: L2 Admission Control
|
|
|
5f9769 |
* Generic admission control flows (without inport check).
|
|
|
5f9769 |
*/
|
|
|
5f9769 |
@@ -10614,6 +10680,9 @@ build_lrouter_ipv4_ip_input(struct ovn_port *op,
|
|
|
5f9769 |
&op->nbrp->header_);
|
|
|
5f9769 |
}
|
|
|
5f9769 |
|
|
|
5f9769 |
+ /* BFD msg handling */
|
|
|
5f9769 |
+ build_lrouter_bfd_flows(lflows, op);
|
|
|
5f9769 |
+
|
|
|
5f9769 |
/* ICMP time exceeded */
|
|
|
5f9769 |
for (int i = 0; i < op->lrp_networks.n_ipv4_addrs; i++) {
|
|
|
5f9769 |
ds_clear(match);
|
|
|
5f9769 |
@@ -12724,7 +12793,7 @@ ovnnb_db_run(struct northd_context *ctx,
|
|
|
5f9769 |
build_ip_mcast(ctx, datapaths);
|
|
|
5f9769 |
build_mcast_groups(ctx, datapaths, ports, &mcast_groups, &igmp_groups);
|
|
|
5f9769 |
build_meter_groups(ctx, &meter_groups);
|
|
|
5f9769 |
- build_bfd_table(ctx, &bfd_connections);
|
|
|
5f9769 |
+ build_bfd_table(ctx, &bfd_connections, ports);
|
|
|
5f9769 |
build_lflows(ctx, datapaths, ports, &port_groups, &mcast_groups,
|
|
|
5f9769 |
&igmp_groups, &meter_groups, &lbs;;
|
|
|
5f9769 |
ovn_update_ipv6_prefix(ports);
|
|
|
5f9769 |
diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
|
|
|
5f9769 |
index ce6c44db4..eee004328 100644
|
|
|
5f9769 |
--- a/tests/ovn-northd.at
|
|
|
5f9769 |
+++ b/tests/ovn-northd.at
|
|
|
5f9769 |
@@ -2322,3 +2322,58 @@ sed 's/reg8\[[0..15\]] == [[0-9]]*/reg8\[[0..15\]] == <cleared>/' | sort], [0],
|
|
|
5f9769 |
])
|
|
|
5f9769 |
|
|
|
5f9769 |
AT_CLEANUP
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+AT_SETUP([ovn -- check BFD config propagation to SBDB])
|
|
|
5f9769 |
+AT_KEYWORDS([northd-bfd])
|
|
|
5f9769 |
+ovn_start
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+check ovn-nbctl --wait=sb lr-add r0
|
|
|
5f9769 |
+for i in $(seq 1 4); do
|
|
|
5f9769 |
+ check ovn-nbctl --wait=sb lrp-add r0 r0-sw$i 00:00:00:00:00:0$i 192.168.$i.1/24
|
|
|
5f9769 |
+ check ovn-nbctl --wait=sb ls-add sw$i
|
|
|
5f9769 |
+ check ovn-nbctl --wait=sb lsp-add sw$i sw$i-r0
|
|
|
5f9769 |
+ check ovn-nbctl --wait=sb lsp-set-type sw$i-r0 router
|
|
|
5f9769 |
+ check ovn-nbctl --wait=sb lsp-set-options sw$i-r0 router-port=r0-sw$i
|
|
|
5f9769 |
+ check ovn-nbctl --wait=sb lsp-set-addresses sw$i-r0 00:00:00:00:00:0$i
|
|
|
5f9769 |
+done
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+uuid=$(ovn-nbctl create bfd logical_port=r0-sw1 dst_ip=192.168.10.2 status=down min_tx=250 min_rx=250 detect_mult=10)
|
|
|
5f9769 |
+ovn-nbctl create bfd logical_port=r0-sw2 dst_ip=192.168.20.2 status=down min_tx=500 min_rx=500 detect_mult=20
|
|
|
5f9769 |
+ovn-nbctl create bfd logical_port=r0-sw3 dst_ip=192.168.30.2 status=down
|
|
|
5f9769 |
+ovn-nbctl create bfd logical_port=r0-sw4 dst_ip=192.168.40.2 status=down min_tx=0 detect_mult=0
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+check_column 10 bfd detect_mult logical_port=r0-sw1
|
|
|
5f9769 |
+check_column "192.168.10.2" bfd dst_ip logical_port=r0-sw1
|
|
|
5f9769 |
+check_column 250 bfd min_rx logical_port=r0-sw1
|
|
|
5f9769 |
+check_column 250 bfd min_tx logical_port=r0-sw1
|
|
|
5f9769 |
+check_column admin_down bfd status logical_port=r0-sw1
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+check_column 20 bfd detect_mult logical_port=r0-sw2
|
|
|
5f9769 |
+check_column "192.168.20.2" bfd dst_ip logical_port=r0-sw2
|
|
|
5f9769 |
+check_column 500 bfd min_rx logical_port=r0-sw2
|
|
|
5f9769 |
+check_column 500 bfd min_tx logical_port=r0-sw2
|
|
|
5f9769 |
+check_column admin_down bfd status logical_port=r0-sw2
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+check_column 5 bfd detect_mult logical_port=r0-sw3
|
|
|
5f9769 |
+check_column "192.168.30.2" bfd dst_ip logical_port=r0-sw3
|
|
|
5f9769 |
+check_column 1000 bfd min_rx logical_port=r0-sw3
|
|
|
5f9769 |
+check_column 1000 bfd min_tx logical_port=r0-sw3
|
|
|
5f9769 |
+check_column admin_down bfd status logical_port=r0-sw3
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+uuid=$(fetch_column nb:bfd _uuid logical_port=r0-sw1)
|
|
|
5f9769 |
+check ovn-nbctl set bfd $uuid min_tx=1000
|
|
|
5f9769 |
+check ovn-nbctl set bfd $uuid min_rx=1000
|
|
|
5f9769 |
+check ovn-nbctl set bfd $uuid detect_mult=100
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+uuid_2=$(fetch_column nb:bfd _uuid logical_port=r0-sw2)
|
|
|
5f9769 |
+check ovn-nbctl clear bfd $uuid_2 min_rx
|
|
|
5f9769 |
+check_column 1000 bfd min_rx logical_port=r0-sw2
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+check_column 1000 bfd min_tx logical_port=r0-sw1
|
|
|
5f9769 |
+check_column 1000 bfd min_rx logical_port=r0-sw1
|
|
|
5f9769 |
+check_column 100 bfd detect_mult logical_port=r0-sw1
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ovn-nbctl destroy bfd $uuid
|
|
|
5f9769 |
+check_row_count bfd 2
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+AT_CLEANUP
|
|
|
5f9769 |
--
|
|
|
5f9769 |
2.29.2
|
|
|
5f9769 |
|