DHCP client extends its lease by unicasting a DHCPREQUEST to its
original DHCP server when the T1 timer fires (typically at 50% of
the lease).  If that DHCPREQUEST gets no response, the T2 timer
fires (typically at 87.5% of the lease) and the client enters the
REBINDING state, where it broadcasts a DHCPREQUEST using its
currently leased IP as the source address (rather than 0.0.0.0).

Today OVN's DHCP relay only matches DHCPREQUEST packets whose source
IP is 0.0.0.0, so the broadcast DHCPREQUEST sent by a client in the
REBINDING state is not matched by any relay flow and is dropped.
The lease cannot be renewed through the relay and the client
eventually falls back to a fresh DISCOVER.

Extend the relay to also forward DHCPREQUEST packets whose source IP
lies in the relay LRP's subnet by widening the source-IP match of
the DHCP relay request flows to the set
ip4.src == {0.0.0.0, <lrp_cidr>}, where <lrp_cidr> is the CIDR of
the relay Logical_Router_Port.  The set is applied to:

- The priority-100 logical switch flow in ls_in_l2_lkup that
forwards client DHCP broadcasts to the relay LRP-attachment
port.
- The logical router lr_in_ip_input priority-110
dhcp_relay_req_chk flow.
- The lr_in_dhcp_relay_req priority-100 forward and priority-1
drop flows.

The behaviour is controlled by a new NB_Global option:

options:dhcp_relay_handle_rebind   boolean (default 'true')

Setting it to 'false' restores the previous behaviour and matches
only ip4.src == 0.0.0.0.

Signed-off-by: Naveen Yerramneni <[email protected]>
Acked-by: Aditya Mehakare <[email protected]>
Acked-by: Huzaifa Calcuttawala <[email protected]>
---
 Documentation/ref/ovn-logical-flows.7.rst | 32 ++++++++------
 NEWS                                      |  5 +++
 northd/en-global-config.c                 |  5 +++
 northd/northd.c                           | 51 +++++++++++++++++++----
 ovn-nb.xml                                | 18 ++++++++
 tests/ovn-northd.at                       | 48 ++++++++++++++++++---
 tests/ovn.at                              |  9 +++-
 7 files changed, 140 insertions(+), 28 deletions(-)

diff --git a/Documentation/ref/ovn-logical-flows.7.rst 
b/Documentation/ref/ovn-logical-flows.7.rst
index 0b69d7bb0..0d46301b3 100644
--- a/Documentation/ref/ovn-logical-flows.7.rst
+++ b/Documentation/ref/ovn-logical-flows.7.rst
@@ -1392,7 +1392,9 @@ This table implements switching behavior.  It contains 
these logical flows:
 
 - A priority-100 flow that forwards all DHCP broadcast packets coming from VIFs
   to the logical router port's MAC when DHCP relay is enabled on the logical
-  switch.
+  switch.  By default the ``ip4.src`` match is the set ``{0.0.0.0, lrp_cidr}``.
+  If ``dhcp_relay_handle_rebind`` in the ``NB_Global`` ``options`` column is 
set
+  to ``false`` the match is ``ip4.src == 0.0.0.0`` only.
 
 - A priority-100 flow that matches ``reg8[23] == 1`` and does ``output`` 
action.
   This ensures that packets that got injected back into this table from egress
@@ -2199,9 +2201,11 @@ contains the following flows to implement very basic IP 
host functionality.
 - For each logical router port configured with DHCP relay the following
   priority-110 flows are added to manage the DHCP relay traffic:
 
-  - if ``inport`` is lrp and ``ip4.src == 0.0.0.0`` and ``ip4.dst ==
-    255.255.255.255`` and ``ip4.frag == 0`` and ``udp.src == 68`` and ``udp.dst
-    == 67``, the ``dhcp_relay_req_chk`` action is executed. ::
+  - if ``inport`` is lrp and ``ip4.src == {0.0.0.0, lrp_cidr}`` and ``ip4.dst
+    == 255.255.255.255`` and ``ip4.frag == 0`` and ``udp.src == 68`` and
+    ``udp.dst == 67``, the ``dhcp_relay_req_chk`` action is executed.  Setting
+    ``dhcp_relay_handle_rebind`` in the ``NB_Global`` ``options`` column to
+    ``false`` restricts the ``ip4.src`` match to ``0.0.0.0`` only. ::
 
         reg9[7] = dhcp_relay_req_chk(lrp_ip, dhcp_server_ip);next
 
@@ -2499,10 +2503,12 @@ This stage process the DHCP request packets on which 
``dhcp_relay_req_chk``
 action is applied in the IP input stage.
 
 - A priority-100 logical flow is added for each logical router port configured
-  with DHCP relay that matches ``inport`` is lrp and ``ip4.src == 0.0.0.0`` and
-  ``ip4.dst == 255.255.255.255`` and ``udp.src == 68`` and ``udp.dst == 67`` 
and
-  ``reg9[7] == 1`` and applies following actions. If ``reg9[7]`` is set to 1
-  then, ``dhcp_relay_req_chk`` action was successful. ::
+  with DHCP relay that matches ``inport`` is lrp and ``ip4.src == {0.0.0.0,
+  lrp_cidr}`` and ``ip4.dst == 255.255.255.255`` and ``udp.src == 68`` and
+  ``udp.dst == 67`` and ``reg9[7] == 1`` and applies following actions. If
+  ``reg9[7]`` is set to 1 then, ``dhcp_relay_req_chk`` action was successful.
+  Setting ``dhcp_relay_handle_rebind`` in the ``NB_Global`` ``options`` column
+  to ``false`` restricts the ``ip4.src`` match to ``0.0.0.0`` only. ::
 
       ip4.src=lrp ip;
       ip4.dst=dhcp server ip;
@@ -2510,10 +2516,12 @@ action is applied in the IP input stage.
       next;
 
 - A priority-1 logical flow is added for each logical router port configured
-  with DHCP relay that matches ``inport`` is lrp and ``ip4.src == 0.0.0.0`` and
-  ``ip4.dst == 255.255.255.255`` and ``udp.src == 68`` and ``udp.dst == 67`` 
and
-  ``reg9[7] == 0`` and drops the packet. If ``reg9[7]`` is set to 0 then,
-  ``dhcp_relay_req_chk`` action was unsuccessful.
+  with DHCP relay that matches ``inport`` is lrp and ``ip4.src == {0.0.0.0,
+  lrp_cidr}`` and ``ip4.dst == 255.255.255.255`` and ``udp.src == 68`` and
+  ``udp.dst == 67`` and ``reg9[7] == 0`` and drops the packet. If ``reg9[7]``
+  is set to 0 then, ``dhcp_relay_req_chk`` action was unsuccessful.  Setting
+  ``dhcp_relay_handle_rebind`` in the ``NB_Global`` ``options`` column to
+  ``false`` restricts the ``ip4.src`` match to ``0.0.0.0`` only.
 
 - A priority-0 flow that matches all packets to advance to the next table.
 
diff --git a/NEWS b/NEWS
index 9839d19b9..4e8df14ae 100644
--- a/NEWS
+++ b/NEWS
@@ -12,6 +12,11 @@ Post v26.03.0
      * Add ECMP/multi-homing support for EVPN FDB entries. FDB entries
        backed by a kernel nexthop group are load-balanced via OpenFlow
        select groups with weighted buckets.
+   - The DHCP relay now also forwards DHCPREQUEST packets whose
+     source IP lies in the relay LRP's subnet, in addition to
+     ip4.src == 0.0.0.0.  Controlled by the new NB_Global option
+     dhcp_relay_handle_rebind (default true); set it to false to
+     match only ip4.src == 0.0.0.0.
 
 OVN v26.03.0 - xxx xx xxxx
 --------------------------
diff --git a/northd/en-global-config.c b/northd/en-global-config.c
index d49ddb94a..1f757a203 100644
--- a/northd/en-global-config.c
+++ b/northd/en-global-config.c
@@ -724,6 +724,11 @@ check_nb_options_out_of_sync(
         return true;
     }
 
+    if (config_out_of_sync(&nb->options, &config_data->nb_options,
+                           "dhcp_relay_handle_rebind", true)) {
+        return true;
+    }
+
     return false;
 }
 
diff --git a/northd/northd.c b/northd/northd.c
index 8305e0428..16c5916a9 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -105,6 +105,11 @@ static bool default_acl_drop;
  * and ports tunnel key allocation (12 bits for each instead of default 16). */
 static bool vxlan_mode;
 
+/* If 'true' (default), DHCP relay flows match both ip4.src == 0.0.0.0
+ * and ip4.src within the relay LRP's CIDR.  If 'false', only
+ * ip4.src == 0.0.0.0 is matched. */
+static bool dhcp_relay_handle_rebind = true;
+
 #define MAX_OVN_TAGS 4096
 
 #define MAX_OVN_NF_GROUP_IDS 256
@@ -10072,14 +10077,25 @@ build_lswitch_dhcp_relay_flows(struct ovn_port *op,
     ds_clear(match);
     ds_clear(actions);
 
+    /* Match 0.0.0.0 and the LRP's CIDR when 'dhcp_relay_handle_rebind'
+     * is enabled (default); match only 0.0.0.0 when disabled. */
+    struct ds src_ip_match = DS_EMPTY_INITIALIZER;
+    if (dhcp_relay_handle_rebind && rp->lrp_networks.n_ipv4_addrs > 0) {
+        ds_put_format(&src_ip_match, "ip4.src == {0.0.0.0, %s/%u}",
+                      rp->lrp_networks.ipv4_addrs[0].network_s,
+                      rp->lrp_networks.ipv4_addrs[0].plen);
+    } else {
+        ds_put_cstr(&src_ip_match, "ip4.src == 0.0.0.0");
+    }
+
     ds_put_format(
         match, "inport == %s && eth.src == %s && "
-        "ip4.src == 0.0.0.0 && ip4.dst == 255.255.255.255 && "
+        "%s && ip4.dst == 255.255.255.255 && "
         "udp.src == 68 && udp.dst == 67",
-        op->json_key, op->lsp_addrs[0].ea_s);
+        op->json_key, op->lsp_addrs[0].ea_s, ds_cstr(&src_ip_match));
     ds_put_format(actions,
                   "eth.dst = %s; outport = %s; next; /* DHCP_RELAY_REQ */",
-                  rp->lrp_networks.ea_s,sp->json_key);
+                  rp->lrp_networks.ea_s, sp->json_key);
     ovn_lflow_add(lflows, op->od,
                   S_SWITCH_IN_L2_LKUP, 100,
                   ds_cstr(match),
@@ -10089,6 +10105,8 @@ build_lswitch_dhcp_relay_flows(struct ovn_port *op,
                   WITH_HINT(&op->nbsp->header_));
     ds_clear(match);
     ds_clear(actions);
+    ds_destroy(&src_ip_match);
+
     free(server_ip_str);
 }
 
@@ -16734,11 +16752,22 @@ build_dhcp_relay_flows_for_lrouter_port(struct 
ovn_port *op,
     ds_clear(match);
     ds_clear(actions);
 
+    /* Match 0.0.0.0 and the LRP's CIDR when 'dhcp_relay_handle_rebind'
+     * is enabled (default); match only 0.0.0.0 when disabled. */
+    struct ds src_ip_match = DS_EMPTY_INITIALIZER;
+    if (dhcp_relay_handle_rebind) {
+        ds_put_format(&src_ip_match, "ip4.src == {0.0.0.0, %s/%u}",
+                      op->lrp_networks.ipv4_addrs[0].network_s,
+                      op->lrp_networks.ipv4_addrs[0].plen);
+    } else {
+        ds_put_cstr(&src_ip_match, "ip4.src == 0.0.0.0");
+    }
+
     ds_put_format(
         match, "inport == %s && "
-        "ip4.src == 0.0.0.0 && ip4.dst == 255.255.255.255 && "
+        "%s && ip4.dst == 255.255.255.255 && "
         "ip.frag == 0 && udp.src == 68 && udp.dst == 67",
-        op->json_key);
+        op->json_key, ds_cstr(&src_ip_match));
     ds_put_format(actions,
                   REGBIT_DHCP_RELAY_REQ_CHK
                   " = dhcp_relay_req_chk(%s, %s);"
@@ -16757,10 +16786,10 @@ build_dhcp_relay_flows_for_lrouter_port(struct 
ovn_port *op,
 
     ds_put_format(
         match, "inport == %s && "
-        "ip4.src == 0.0.0.0 && ip4.dst == 255.255.255.255 && "
+        "%s && ip4.dst == 255.255.255.255 && "
         "udp.src == 68 && udp.dst == 67 && "
         REGBIT_DHCP_RELAY_REQ_CHK,
-        op->json_key);
+        op->json_key, ds_cstr(&src_ip_match));
     ds_put_format(actions,
                   "ip4.src = %s; ip4.dst = %s; udp.src = 67; next; "
                   "/* DHCP_RELAY_REQ */",
@@ -16775,10 +16804,10 @@ build_dhcp_relay_flows_for_lrouter_port(struct 
ovn_port *op,
 
     ds_put_format(
         match, "inport == %s && "
-        "ip4.src == 0.0.0.0 && ip4.dst == 255.255.255.255 && "
+        "%s && ip4.dst == 255.255.255.255 && "
         "udp.src == 68 && udp.dst == 67 && "
         REGBIT_DHCP_RELAY_REQ_CHK" == 0",
-        op->json_key);
+        op->json_key, ds_cstr(&src_ip_match));
     ds_put_format(actions, "drop; /* DHCP_RELAY_REQ */");
 
     ovn_lflow_add(lflows, op->od, S_ROUTER_IN_DHCP_RELAY_REQ, 1,
@@ -16787,6 +16816,7 @@ build_dhcp_relay_flows_for_lrouter_port(struct ovn_port 
*op,
 
     ds_clear(match);
     ds_clear(actions);
+    ds_destroy(&src_ip_match);
 
     ds_put_format(
         match, "ip4.src == %s && ip4.dst == %s && "
@@ -21249,6 +21279,9 @@ ovnnb_db_run(struct northd_input *input_data,
                                               false);
     use_common_zone = smap_get_bool(input_data->nb_options, "use_common_zone",
                                     false);
+    dhcp_relay_handle_rebind = smap_get_bool(input_data->nb_options,
+                                             "dhcp_relay_handle_rebind",
+                                             true);
 
     vxlan_mode = input_data->vxlan_mode;
 
diff --git a/ovn-nb.xml b/ovn-nb.xml
index 2e8a6a6f1..f5fb775b5 100644
--- a/ovn-nb.xml
+++ b/ovn-nb.xml
@@ -464,6 +464,24 @@
         </p>
       </column>
 
+      <column name="options" key="dhcp_relay_handle_rebind"
+              type='{"type": "boolean"}'>
+        <p>
+          Default is <code>true</code>.  The DHCP relay forwards both
+          broadcast DHCPREQUEST packets sent with no source IP
+          assigned and those sent with the client's currently leased
+          IP as the source address.  The latter are typically sent by
+          clients in the REBINDING state (T2 timer expiry) when they
+          cannot reach their original DHCP server.
+        </p>
+
+        <p>
+          Set to <code>false</code> to forward only DHCPREQUEST
+          packets sent with no source IP assigned.  Refer to
+          <code>ovn-northd</code>(8) for the exact logical-flow match.
+        </p>
+      </column>
+
       <group title="Options for services health check confguration">
         <p>
           These options are used when health configuration is enabled for
diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
index 074b1526b..52b4f78a0 100644
--- a/tests/ovn-northd.at
+++ b/tests/ovn-northd.at
@@ -13394,23 +13394,43 @@ check ovn-nbctl --wait=sb sync
 ovn-sbctl lflow-list > lflows
 AT_CAPTURE_FILE([lflows])
 
+# Default: match the set {0.0.0.0, lrp_cidr}.
 AT_CHECK([grep -e "DHCP_RELAY_" lflows | sed 's/table=../table=??/'], [0], [dnl
-  table=??(lr_in_ip_input     ), priority=110  , match=(inport == "lrp1" && 
ip4.src == 0.0.0.0 && ip4.dst == 255.255.255.255 && ip.frag == 0 && udp.src == 
68 && udp.dst == 67), action=(reg9[[7]] = dhcp_relay_req_chk(192.168.1.1, 
172.16.1.1);next; /* DHCP_RELAY_REQ */)
+  table=??(lr_in_ip_input     ), priority=110  , match=(inport == "lrp1" && 
ip4.src == {0.0.0.0, 192.168.1.0/24} && ip4.dst == 255.255.255.255 && ip.frag 
== 0 && udp.src == 68 && udp.dst == 67), action=(reg9[[7]] = 
dhcp_relay_req_chk(192.168.1.1, 172.16.1.1);next; /* DHCP_RELAY_REQ */)
   table=??(lr_in_ip_input     ), priority=110  , match=(ip4.src == 172.16.1.1 
&& ip4.dst == 192.168.1.1 && ip.frag == 0 && udp.src == 67 && udp.dst == 67), 
action=(next; /* DHCP_RELAY_RESP */)
-  table=??(lr_in_dhcp_relay_req), priority=100  , match=(inport == "lrp1" && 
ip4.src == 0.0.0.0 && ip4.dst == 255.255.255.255 && udp.src == 68 && udp.dst == 
67 && reg9[[7]]), action=(ip4.src = 192.168.1.1; ip4.dst = 172.16.1.1; udp.src 
= 67; next; /* DHCP_RELAY_REQ */)
-  table=??(lr_in_dhcp_relay_req), priority=1    , match=(inport == "lrp1" && 
ip4.src == 0.0.0.0 && ip4.dst == 255.255.255.255 && udp.src == 68 && udp.dst == 
67 && reg9[[7]] == 0), action=(drop; /* DHCP_RELAY_REQ */)
+  table=??(lr_in_dhcp_relay_req), priority=100  , match=(inport == "lrp1" && 
ip4.src == {0.0.0.0, 192.168.1.0/24} && ip4.dst == 255.255.255.255 && udp.src 
== 68 && udp.dst == 67 && reg9[[7]]), action=(ip4.src = 192.168.1.1; ip4.dst = 
172.16.1.1; udp.src = 67; next; /* DHCP_RELAY_REQ */)
+  table=??(lr_in_dhcp_relay_req), priority=1    , match=(inport == "lrp1" && 
ip4.src == {0.0.0.0, 192.168.1.0/24} && ip4.dst == 255.255.255.255 && udp.src 
== 68 && udp.dst == 67 && reg9[[7]] == 0), action=(drop; /* DHCP_RELAY_REQ */)
   table=??(lr_in_dhcp_relay_resp_chk), priority=100  , match=(ip4.src == 
172.16.1.1 && ip4.dst == 192.168.1.1 && udp.src == 67 && udp.dst == 67), 
action=(reg2 = ip4.dst; reg9[[8]] = dhcp_relay_resp_chk(192.168.1.1, 
172.16.1.1); next; /* DHCP_RELAY_RESP */)
   table=??(lr_in_dhcp_relay_resp), priority=100  , match=(ip4.src == 
172.16.1.1 && reg2 == 192.168.1.1 && udp.src == 67 && udp.dst == 67 && 
reg9[[8]]), action=(ip4.src = 192.168.1.1; udp.dst = 68; outport = "lrp1"; 
output; /* DHCP_RELAY_RESP */)
   table=??(lr_in_dhcp_relay_resp), priority=1    , match=(ip4.src == 
172.16.1.1 && reg2 == 192.168.1.1 && udp.src == 67 && udp.dst == 67 && 
reg9[[8]] == 0), action=(drop; /* DHCP_RELAY_RESP */)
-  table=??(ls_in_l2_lkup      ), priority=100  , match=(inport == "ls0-port1" 
&& eth.src == 02:00:00:00:00:10 && ip4.src == 0.0.0.0 && ip4.dst == 
255.255.255.255 && udp.src == 68 && udp.dst == 67), action=(eth.dst = 
02:00:00:00:00:01; outport = "lrp1-attachment"; next; /* DHCP_RELAY_REQ */)
+  table=??(ls_in_l2_lkup      ), priority=100  , match=(inport == "ls0-port1" 
&& eth.src == 02:00:00:00:00:10 && ip4.src == {0.0.0.0, 192.168.1.0/24} && 
ip4.dst == 255.255.255.255 && udp.src == 68 && udp.dst == 67), action=(eth.dst 
= 02:00:00:00:00:01; outport = "lrp1-attachment"; next; /* DHCP_RELAY_REQ */)
 ])
 
-# Set invalid dhcp_relay_port in ls0
+# Invalid dhcp_relay_port: the ls_in_l2_lkup flow is suppressed; the
+# logical router flows keep the default match.
 check ovn-nbctl --wait=sb set Logical_Switch ls0 
other_config:dhcp_relay_port=foo
 
 ovn-sbctl lflow-list > lflows
 AT_CAPTURE_FILE([lflows])
 
+AT_CHECK([grep -e "DHCP_RELAY_" lflows | sed 's/table=../table=??/'], [0], [dnl
+  table=??(lr_in_ip_input     ), priority=110  , match=(inport == "lrp1" && 
ip4.src == {0.0.0.0, 192.168.1.0/24} && ip4.dst == 255.255.255.255 && ip.frag 
== 0 && udp.src == 68 && udp.dst == 67), action=(reg9[[7]] = 
dhcp_relay_req_chk(192.168.1.1, 172.16.1.1);next; /* DHCP_RELAY_REQ */)
+  table=??(lr_in_ip_input     ), priority=110  , match=(ip4.src == 172.16.1.1 
&& ip4.dst == 192.168.1.1 && ip.frag == 0 && udp.src == 67 && udp.dst == 67), 
action=(next; /* DHCP_RELAY_RESP */)
+  table=??(lr_in_dhcp_relay_req), priority=100  , match=(inport == "lrp1" && 
ip4.src == {0.0.0.0, 192.168.1.0/24} && ip4.dst == 255.255.255.255 && udp.src 
== 68 && udp.dst == 67 && reg9[[7]]), action=(ip4.src = 192.168.1.1; ip4.dst = 
172.16.1.1; udp.src = 67; next; /* DHCP_RELAY_REQ */)
+  table=??(lr_in_dhcp_relay_req), priority=1    , match=(inport == "lrp1" && 
ip4.src == {0.0.0.0, 192.168.1.0/24} && ip4.dst == 255.255.255.255 && udp.src 
== 68 && udp.dst == 67 && reg9[[7]] == 0), action=(drop; /* DHCP_RELAY_REQ */)
+  table=??(lr_in_dhcp_relay_resp_chk), priority=100  , match=(ip4.src == 
172.16.1.1 && ip4.dst == 192.168.1.1 && udp.src == 67 && udp.dst == 67), 
action=(reg2 = ip4.dst; reg9[[8]] = dhcp_relay_resp_chk(192.168.1.1, 
172.16.1.1); next; /* DHCP_RELAY_RESP */)
+  table=??(lr_in_dhcp_relay_resp), priority=100  , match=(ip4.src == 
172.16.1.1 && reg2 == 192.168.1.1 && udp.src == 67 && udp.dst == 67 && 
reg9[[8]]), action=(ip4.src = 192.168.1.1; udp.dst = 68; outport = "lrp1"; 
output; /* DHCP_RELAY_RESP */)
+  table=??(lr_in_dhcp_relay_resp), priority=1    , match=(ip4.src == 
172.16.1.1 && reg2 == 192.168.1.1 && udp.src == 67 && udp.dst == 67 && 
reg9[[8]] == 0), action=(drop; /* DHCP_RELAY_RESP */)
+])
+
+# Restore the relay port and disable dhcp_relay_handle_rebind: the
+# relay flows now match only ip4.src == 0.0.0.0.
+check ovn-nbctl set Logical_Switch ls0 
other_config:dhcp_relay_port=lrp1-attachment
+check ovn-nbctl --wait=sb set NB_Global . 
options:dhcp_relay_handle_rebind=false
+
+ovn-sbctl lflow-list > lflows
+AT_CAPTURE_FILE([lflows])
+
 AT_CHECK([grep -e "DHCP_RELAY_" lflows | sed 's/table=../table=??/'], [0], [dnl
   table=??(lr_in_ip_input     ), priority=110  , match=(inport == "lrp1" && 
ip4.src == 0.0.0.0 && ip4.dst == 255.255.255.255 && ip.frag == 0 && udp.src == 
68 && udp.dst == 67), action=(reg9[[7]] = dhcp_relay_req_chk(192.168.1.1, 
172.16.1.1);next; /* DHCP_RELAY_REQ */)
   table=??(lr_in_ip_input     ), priority=110  , match=(ip4.src == 172.16.1.1 
&& ip4.dst == 192.168.1.1 && ip.frag == 0 && udp.src == 67 && udp.dst == 67), 
action=(next; /* DHCP_RELAY_RESP */)
@@ -13419,6 +13439,24 @@ AT_CHECK([grep -e "DHCP_RELAY_" lflows | sed 
's/table=../table=??/'], [0], [dnl
   table=??(lr_in_dhcp_relay_resp_chk), priority=100  , match=(ip4.src == 
172.16.1.1 && ip4.dst == 192.168.1.1 && udp.src == 67 && udp.dst == 67), 
action=(reg2 = ip4.dst; reg9[[8]] = dhcp_relay_resp_chk(192.168.1.1, 
172.16.1.1); next; /* DHCP_RELAY_RESP */)
   table=??(lr_in_dhcp_relay_resp), priority=100  , match=(ip4.src == 
172.16.1.1 && reg2 == 192.168.1.1 && udp.src == 67 && udp.dst == 67 && 
reg9[[8]]), action=(ip4.src = 192.168.1.1; udp.dst = 68; outport = "lrp1"; 
output; /* DHCP_RELAY_RESP */)
   table=??(lr_in_dhcp_relay_resp), priority=1    , match=(ip4.src == 
172.16.1.1 && reg2 == 192.168.1.1 && udp.src == 67 && udp.dst == 67 && 
reg9[[8]] == 0), action=(drop; /* DHCP_RELAY_RESP */)
+  table=??(ls_in_l2_lkup      ), priority=100  , match=(inport == "ls0-port1" 
&& eth.src == 02:00:00:00:00:10 && ip4.src == 0.0.0.0 && ip4.dst == 
255.255.255.255 && udp.src == 68 && udp.dst == 67), action=(eth.dst = 
02:00:00:00:00:01; outport = "lrp1-attachment"; next; /* DHCP_RELAY_REQ */)
+])
+
+# Remove the option: flows revert to the default match.
+check ovn-nbctl --wait=sb remove NB_Global . options dhcp_relay_handle_rebind
+
+ovn-sbctl lflow-list > lflows
+AT_CAPTURE_FILE([lflows])
+
+AT_CHECK([grep -e "DHCP_RELAY_" lflows | sed 's/table=../table=??/'], [0], [dnl
+  table=??(lr_in_ip_input     ), priority=110  , match=(inport == "lrp1" && 
ip4.src == {0.0.0.0, 192.168.1.0/24} && ip4.dst == 255.255.255.255 && ip.frag 
== 0 && udp.src == 68 && udp.dst == 67), action=(reg9[[7]] = 
dhcp_relay_req_chk(192.168.1.1, 172.16.1.1);next; /* DHCP_RELAY_REQ */)
+  table=??(lr_in_ip_input     ), priority=110  , match=(ip4.src == 172.16.1.1 
&& ip4.dst == 192.168.1.1 && ip.frag == 0 && udp.src == 67 && udp.dst == 67), 
action=(next; /* DHCP_RELAY_RESP */)
+  table=??(lr_in_dhcp_relay_req), priority=100  , match=(inport == "lrp1" && 
ip4.src == {0.0.0.0, 192.168.1.0/24} && ip4.dst == 255.255.255.255 && udp.src 
== 68 && udp.dst == 67 && reg9[[7]]), action=(ip4.src = 192.168.1.1; ip4.dst = 
172.16.1.1; udp.src = 67; next; /* DHCP_RELAY_REQ */)
+  table=??(lr_in_dhcp_relay_req), priority=1    , match=(inport == "lrp1" && 
ip4.src == {0.0.0.0, 192.168.1.0/24} && ip4.dst == 255.255.255.255 && udp.src 
== 68 && udp.dst == 67 && reg9[[7]] == 0), action=(drop; /* DHCP_RELAY_REQ */)
+  table=??(lr_in_dhcp_relay_resp_chk), priority=100  , match=(ip4.src == 
172.16.1.1 && ip4.dst == 192.168.1.1 && udp.src == 67 && udp.dst == 67), 
action=(reg2 = ip4.dst; reg9[[8]] = dhcp_relay_resp_chk(192.168.1.1, 
172.16.1.1); next; /* DHCP_RELAY_RESP */)
+  table=??(lr_in_dhcp_relay_resp), priority=100  , match=(ip4.src == 
172.16.1.1 && reg2 == 192.168.1.1 && udp.src == 67 && udp.dst == 67 && 
reg9[[8]]), action=(ip4.src = 192.168.1.1; udp.dst = 68; outport = "lrp1"; 
output; /* DHCP_RELAY_RESP */)
+  table=??(lr_in_dhcp_relay_resp), priority=1    , match=(ip4.src == 
172.16.1.1 && reg2 == 192.168.1.1 && udp.src == 67 && udp.dst == 67 && 
reg9[[8]] == 0), action=(drop; /* DHCP_RELAY_RESP */)
+  table=??(ls_in_l2_lkup      ), priority=100  , match=(inport == "ls0-port1" 
&& eth.src == 02:00:00:00:00:10 && ip4.src == {0.0.0.0, 192.168.1.0/24} && 
ip4.dst == 255.255.255.255 && udp.src == 68 && udp.dst == 67), action=(eth.dst 
= 02:00:00:00:00:01; outport = "lrp1-attachment"; next; /* DHCP_RELAY_REQ */)
 ])
 
 # Clear the dhcp_relay from lrp1
diff --git a/tests/ovn.at b/tests/ovn.at
index fbaa63d99..0e2299b81 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -41221,8 +41221,12 @@ sid=$src_ip
 # send packet
 send_dhcp_packet $src_mac $src_ip $dst_mac $dst_ip 01 01 $yiaddr $giaddr $sid 
vif0
 
+# The default set match ip4.src == {0.0.0.0, lrp_cidr} compiles to
+# two OF flows; only the 0.0.0.0 one sees the DISCOVER packet.
+# Sort for stable ordering.
 OVS_WAIT_FOR_OUTPUT([ovs-ofctl dump-flows br-int table=$dhcp_relay_req_table | 
grep -v NXST | grep 255.255.255.255 | grep resubmit |
-cut -d ' ' -f5-5 | sed "s/,//"], [0], [dnl
+cut -d ' ' -f5-5 | sed "s/,//" | sort], [0], [dnl
+n_packets=0
 n_packets=1
 ])
 
@@ -41233,7 +41237,8 @@ giaddr=`ip_to_hex 192.168.1.1`
 send_dhcp_packet $src_mac $src_ip $dst_mac $dst_ip 01 01 $yiaddr $giaddr $sid 
vif0
 
 OVS_WAIT_FOR_OUTPUT([ovs-ofctl dump-flows br-int table=$dhcp_relay_req_table | 
grep -v NXST | grep 255.255.255.255 | grep drop |
-cut -d ' ' -f5-5 | sed "s/,//"], [0], [dnl
+cut -d ' ' -f5-5 | sed "s/,//" | sort], [0], [dnl
+n_packets=0
 n_packets=1
 ])
 
-- 
2.43.5

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to