diff mbox series

[ovs-dev,v7,4/5] bfd: support demand mode on rx side

Message ID 3bd14277d2d556af2256483324753b232beeb373.1609868820.git.lorenzo.bianconi@redhat.com
State Changes Requested
Headers show
Series introduce BFD support in ovn-controller | expand

Commit Message

Lorenzo Bianconi Jan. 5, 2021, 5:55 p.m. UTC
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 <lorenzo.bianconi@redhat.com>
---
 controller/pinctrl.c | 105 ++++++++++++++++++++++++++++---------------
 1 file changed, 68 insertions(+), 37 deletions(-)
diff mbox series

Patch

diff --git a/controller/pinctrl.c b/controller/pinctrl.c
index 359bbb743..36953f28a 100644
--- a/controller/pinctrl.c
+++ b/controller/pinctrl.c
@@ -330,7 +330,8 @@  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(const struct flow *ip_flow, struct dp_packet *pkt_in)
+pinctrl_handle_bfd_msg(struct rconn *swconn, const struct flow *ip_flow,
+                       struct dp_packet *pkt_in)
                        OVS_REQUIRES(pinctrl_mutex);
 static void bfd_monitor_run(struct ovsdb_idl_txn *ovnsb_idl_txn,
                             const struct sbrec_bfd_table *bfd_table,
@@ -2981,7 +2982,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(&headers, &packet);
+        pinctrl_handle_bfd_msg(swconn, &headers, &packet);
         ovs_mutex_unlock(&pinctrl_mutex);
         break;
 
@@ -6411,6 +6412,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;
@@ -6496,7 +6499,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;
@@ -6528,13 +6532,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
 bfd_monitor_need_update(void)
 {
@@ -6607,39 +6652,11 @@  bfd_monitor_send_msg(struct rconn *swconn, long long int *bfd_time)
             continue;
         }
 
-        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,
-        };
+        if (entry->remote_demand_mode) {
+            continue;
+        }
 
-        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);
+        pinctrl_send_bfd_tx_msg(swconn, entry, false);
 
         tx_timeout = MAX(entry->local_min_tx, entry->remote_min_rx);
         tx_timeout -= random_range((tx_timeout * 25) / 100);
@@ -6696,6 +6713,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;
@@ -6705,7 +6726,8 @@  pinctrl_check_bfd_msg(const struct flow *ip_flow, struct dp_packet *pkt_in)
 }
 
 static void
-pinctrl_handle_bfd_msg(const struct flow *ip_flow, struct dp_packet *pkt_in)
+pinctrl_handle_bfd_msg(struct rconn *swconn, const struct flow *ip_flow,
+                       struct dp_packet *pkt_in)
     OVS_REQUIRES(pinctrl_mutex)
 {
     if (!pinctrl_check_bfd_msg(ip_flow, pkt_in)) {
@@ -6775,6 +6797,15 @@  pinctrl_handle_bfd_msg(const struct flow *ip_flow, struct dp_packet *pkt_in)
         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) {