When a Logical_Router_Port has DHCP relay enabled and multiple IPv4
addresses configured, ovn-northd needs to pick one of them as the
relay agent address (giaddr).  This choice was hard-coded to
lrp_networks.ipv4_addrs[0] which depends entirely on internal
ordering.

The 'networks' column on Logical_Router_Port is an OVSDB set whose
elements are sorted by strcmp() on the raw CIDR strings.
This makes lrp_networks.ipv4_addrs[0] simply whichever CIDR sorts
first as a string, which may not match the address intended as
the "DHCP relay" address of the port.

Add a new key 'options:primary_ipv4' on Logical_Router_Port.  When
set, it must be an IPv4 host address that equals one of the port's
configured addresses; ovn-northd then uses that address as the
giaddr in all DHCP relay flows it emits for the port.  When unset,
behavior is unchanged: ovn-northd falls back to
lrp_networks.ipv4_addrs[0] (whichever CIDR sorts first as a string),
so existing deployments are unaffected on upgrade.

If 'options:primary_ipv4' is set but is not a valid IPv4 address or
does not match any address in 'networks', ovn-northd treats it as a
misconfiguration: it logs a warning and skips emitting DHCP relay
flows for the port rather than silently falling back to the default
address.

This option is intended to be reusable by any feature that needs a
single representative IPv4 for the port.

Reported-by: Dumitru Ceara <[email protected]>
Signed-off-by: Naveen Yerramneni <[email protected]>
Acked-by: Aditya Mehakare <[email protected]>
Acked-by: Huzaifa Calcuttawala <[email protected]>
---
V2:
   - Rebase on top of latest main.
---

 NEWS                |  8 ++++
 northd/northd.c     | 97 ++++++++++++++++++++++++++++++++++++---------
 ovn-nb.xml          | 29 ++++++++++++++
 tests/ovn-northd.at | 76 +++++++++++++++++++++++++++++++++++
 4 files changed, 191 insertions(+), 19 deletions(-)

diff --git a/NEWS b/NEWS
index 582696e2c..be51e05c2 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,13 @@
 Post v26.03.0
 -------------
+   - Logical_Router_Port: Added a new "options:primary_ipv4" key that
+     selects which of the port's IPv4 addresses is treated as the port's
+     "primary" address.  DHCP Relay uses it as the relay agent address
+     (giaddr) in relayed DHCP packets.  When unset, ovn-northd picks the
+     same address it picked before (whichever CIDR in "networks" sorts
+     first as a string), so existing deployments are unaffected;
+     deployments that need a specific address on a multi-IP port can
+     pin it via the new option.
    - Added Transit Switch port support with new ovn-ic-nbctl 'tsp-add',
      'tsp-del' and 'tsp-set-addr' commands.
    - Added ability to set any "ipsec_*" NB_Global option to configure the
diff --git a/northd/northd.c b/northd/northd.c
index aa332c449..2cdb6f26c 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -10073,6 +10073,9 @@ ls_dhcp_relay_port(const struct ovn_datapath *od)
     return smap_get(&od->nbs->other_config, "dhcp_relay_port");
 }
 
+static const struct ipv4_netaddr *lrp_primary_ipv4_addr(
+    const struct ovn_port *op);
+
 static void
 build_lswitch_dhcp_relay_flows(struct ovn_port *op,
                                const struct hmap *ls_ports,
@@ -10112,6 +10115,12 @@ build_lswitch_dhcp_relay_flows(struct ovn_port *op,
         return;
     }
 
+    /* Use the LRP's primary IPv4 addr for the DHCP relay. */
+    const struct ipv4_netaddr *lrp_ipv4_addr = lrp_primary_ipv4_addr(rp);
+    if (!lrp_ipv4_addr) {
+        return;
+    }
+
     char *server_ip_str = NULL;
     uint16_t port;
     int addr_family;
@@ -10135,8 +10144,7 @@ build_lswitch_dhcp_relay_flows(struct ovn_port *op,
         "ip4.src == {0.0.0.0, %s/%u} && ip4.dst == 255.255.255.255 && "
         "udp.src == 68 && udp.dst == 67",
         op->json_key, op->lsp_addrs[0].ea_s,
-        rp->lrp_networks.ipv4_addrs[0].network_s,
-        rp->lrp_networks.ipv4_addrs[0].plen);
+        lrp_ipv4_addr->network_s, lrp_ipv4_addr->plen);
     ds_put_format(actions,
                   "eth.dst = %s; outport = %s; next; /* DHCP_RELAY_REQ */",
                   rp->lrp_networks.ea_s, sp->json_key);
@@ -16833,6 +16841,57 @@ build_dhcpv6_reply_flows_for_lrouter_port(
     }
 }
 
+/* Resolve the LRP's "primary" IPv4 address - the single representative
+ * IP used by features such as DHCP relay (giaddr).
+ *
+ * If 'options:primary_ipv4' is set, returns the entry from
+ * 'lrp_networks' whose address matches it.  If the option is unset,
+ * returns lrp_networks.ipv4_addrs[0] - the first address from
+ * 'networks' in OVSDB sort order (set members are sorted by strcmp()
+ * on their string form).
+ *
+ * Returns NULL when the port has no IPv4 address at all, or when
+ * 'options:primary_ipv4' is set but is not a valid IPv4 address or
+ * does not match any address on the port.  Callers must skip
+ * emitting flows that need a primary IPv4 in those cases.
+ */
+static const struct ipv4_netaddr *
+lrp_primary_ipv4_addr(const struct ovn_port *op)
+{
+    if (!op->lrp_networks.n_ipv4_addrs) {
+        return NULL;
+    }
+
+    const char *primary_ip = smap_get(&op->nbrp->options, "primary_ipv4");
+
+    if (!primary_ip || !primary_ip[0]) {
+        return &op->lrp_networks.ipv4_addrs[0];
+    }
+
+    ovs_be32 primary_ip4;
+    if (!ip_parse(primary_ip, &primary_ip4)) {
+        static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
+        VLOG_WARN_RL(&rl,
+                     "Logical_Router_Port %s: options:primary_ipv4=%s is "
+                     "not a valid IPv4 address.",
+                     op->nbrp->name, primary_ip);
+        return NULL;
+    }
+
+    for (size_t i = 0; i < op->lrp_networks.n_ipv4_addrs; i++) {
+        if (op->lrp_networks.ipv4_addrs[i].addr == primary_ip4) {
+            return &op->lrp_networks.ipv4_addrs[i];
+        }
+    }
+
+    static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
+    VLOG_WARN_RL(&rl,
+                 "Logical_Router_Port %s: options:primary_ipv4=%s does not "
+                 "match any address in 'networks'.",
+                 op->nbrp->name, primary_ip);
+    return NULL;
+}
+
 static void
 build_dhcp_relay_flows_for_lrouter_port(struct ovn_port *op,
                                         struct lflow_table *lflows,
@@ -16857,6 +16916,12 @@ build_dhcp_relay_flows_for_lrouter_port(struct 
ovn_port *op,
         return;
     }
 
+    /* Use the LRP's primary IPv4 addr for the DHCP relay. */
+    const struct ipv4_netaddr *lrp_ipv4_addr = lrp_primary_ipv4_addr(op);
+    if (!lrp_ipv4_addr) {
+        return;
+    }
+
     int addr_family;
     /* currently not supporting custom port,
      * dhcp server port is always set to 67 when installing flows */
@@ -16880,14 +16945,12 @@ build_dhcp_relay_flows_for_lrouter_port(struct 
ovn_port *op,
         match, "inport == %s && "
         "ip4.src == {0.0.0.0, %s/%u} && ip4.dst == 255.255.255.255 && "
         "ip.frag == 0 && udp.src == 68 && udp.dst == 67",
-        op->json_key,
-        op->lrp_networks.ipv4_addrs[0].network_s,
-        op->lrp_networks.ipv4_addrs[0].plen);
+        op->json_key, lrp_ipv4_addr->network_s, lrp_ipv4_addr->plen);
     ds_put_format(actions,
                   REGBIT_DHCP_RELAY_REQ_CHK
                   " = dhcp_relay_req_chk(%s, %s);"
                   "next; /* DHCP_RELAY_REQ */",
-                  op->lrp_networks.ipv4_addrs[0].addr_s, server_ip_str);
+                  lrp_ipv4_addr->addr_s, server_ip_str);
 
     ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_INPUT, 110, ds_cstr(match),
                   ds_cstr(actions), lflow_ref,
@@ -16904,13 +16967,11 @@ build_dhcp_relay_flows_for_lrouter_port(struct 
ovn_port *op,
         "ip4.src == {0.0.0.0, %s/%u} && ip4.dst == 255.255.255.255 && "
         "udp.src == 68 && udp.dst == 67 && "
         REGBIT_DHCP_RELAY_REQ_CHK,
-        op->json_key,
-        op->lrp_networks.ipv4_addrs[0].network_s,
-        op->lrp_networks.ipv4_addrs[0].plen);
+        op->json_key, lrp_ipv4_addr->network_s, lrp_ipv4_addr->plen);
     ds_put_format(actions,
                   "ip4.src = %s; ip4.dst = %s; udp.src = 67; next; "
                   "/* DHCP_RELAY_REQ */",
-                  op->lrp_networks.ipv4_addrs[0].addr_s, server_ip_str);
+                  lrp_ipv4_addr->addr_s, server_ip_str);
 
     ovn_lflow_add(lflows, op->od, S_ROUTER_IN_DHCP_RELAY_REQ, 100,
                   ds_cstr(match), ds_cstr(actions), lflow_ref,
@@ -16924,9 +16985,7 @@ build_dhcp_relay_flows_for_lrouter_port(struct ovn_port 
*op,
         "ip4.src == {0.0.0.0, %s/%u} && ip4.dst == 255.255.255.255 && "
         "udp.src == 68 && udp.dst == 67 && "
         REGBIT_DHCP_RELAY_REQ_CHK" == 0",
-        op->json_key,
-        op->lrp_networks.ipv4_addrs[0].network_s,
-        op->lrp_networks.ipv4_addrs[0].plen);
+        op->json_key, lrp_ipv4_addr->network_s, lrp_ipv4_addr->plen);
     ds_put_format(actions, "drop; /* DHCP_RELAY_REQ */");
 
     ovn_lflow_add(lflows, op->od, S_ROUTER_IN_DHCP_RELAY_REQ, 1,
@@ -16939,7 +16998,7 @@ build_dhcp_relay_flows_for_lrouter_port(struct ovn_port 
*op,
     ds_put_format(
         match, "ip4.src == %s && ip4.dst == %s && "
         "ip.frag == 0 && udp.src == 67 && udp.dst == 67",
-        server_ip_str, op->lrp_networks.ipv4_addrs[0].addr_s);
+        server_ip_str, lrp_ipv4_addr->addr_s);
     ds_put_format(actions, "next; /* DHCP_RELAY_RESP */");
     ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_INPUT, 110,
                   ds_cstr(match), ds_cstr(actions), lflow_ref,
@@ -16951,12 +17010,12 @@ build_dhcp_relay_flows_for_lrouter_port(struct 
ovn_port *op,
     ds_put_format(
         match, "ip4.src == %s && ip4.dst == %s && "
         "udp.src == 67 && udp.dst == 67",
-        server_ip_str, op->lrp_networks.ipv4_addrs[0].addr_s);
+        server_ip_str, lrp_ipv4_addr->addr_s);
     ds_put_format(actions,
           REG_DHCP_RELAY_DIP_IPV4" = ip4.dst; "
           REGBIT_DHCP_RELAY_RESP_CHK
           " = dhcp_relay_resp_chk(%s, %s); next; /* DHCP_RELAY_RESP */",
-          op->lrp_networks.ipv4_addrs[0].addr_s, server_ip_str);
+          lrp_ipv4_addr->addr_s, server_ip_str);
 
     ovn_lflow_add(lflows, op->od, S_ROUTER_IN_DHCP_RELAY_RESP_CHK, 100,
                   ds_cstr(match), ds_cstr(actions), lflow_ref,
@@ -16974,11 +17033,11 @@ build_dhcp_relay_flows_for_lrouter_port(struct 
ovn_port *op,
         REG_DHCP_RELAY_DIP_IPV4" == %s && "
         "udp.src == 67 && udp.dst == 67 && "
         REGBIT_DHCP_RELAY_RESP_CHK,
-        server_ip_str, op->lrp_networks.ipv4_addrs[0].addr_s);
+        server_ip_str, lrp_ipv4_addr->addr_s);
     ds_put_format(actions,
                   "ip4.src = %s; udp.dst = 68; "
                   "outport = %s; output; /* DHCP_RELAY_RESP */",
-                  op->lrp_networks.ipv4_addrs[0].addr_s, op->json_key);
+                  lrp_ipv4_addr->addr_s, op->json_key);
     ovn_lflow_add(lflows, op->od, S_ROUTER_IN_DHCP_RELAY_RESP, 100,
                   ds_cstr(match), ds_cstr(actions), lflow_ref,
                   WITH_HINT(&op->nbrp->header_));
@@ -16990,7 +17049,7 @@ build_dhcp_relay_flows_for_lrouter_port(struct ovn_port 
*op,
                   REG_DHCP_RELAY_DIP_IPV4" == %s && "
                   "udp.src == 67 && udp.dst == 67 && "
                   REGBIT_DHCP_RELAY_RESP_CHK" == 0",
-                  server_ip_str, op->lrp_networks.ipv4_addrs[0].addr_s);
+                  server_ip_str, lrp_ipv4_addr->addr_s);
     ds_put_format(actions, "drop; /* DHCP_RELAY_RESP */");
     ovn_lflow_add(lflows, op->od, S_ROUTER_IN_DHCP_RELAY_RESP, 1,
                   ds_cstr(match), ds_cstr(actions), lflow_ref,
diff --git a/ovn-nb.xml b/ovn-nb.xml
index 15fb1d7e8..9419a4d4b 100644
--- a/ovn-nb.xml
+++ b/ovn-nb.xml
@@ -4131,6 +4131,35 @@ or
       to <ref table="DHCP_Relay"/> table.
     </column>
 
+    <column name="options" key="primary_ipv4">
+      <p>
+        Optional.  Selects which of the logical router port's IPv4
+        addresses is treated as the port's <em>primary</em> IPv4 address.
+        The value must be a bare IPv4 host address (no prefix length, e.g.
+        <code>10.0.0.1</code>) that equals one of the addresses configured
+        in <ref column="networks"/>.  If the value is not a valid IPv4
+        address or does not match one of the addresses in
+        <ref column="networks"/>, <code>ovn-northd</code> disables any
+        feature that requires a primary IPv4 on this port (e.g. DHCP
+        relay).
+      </p>
+      <p>
+        This option is consumed by DHCP Relay (see
+        <ref column="dhcp_relay"/>), where the primary IPv4 is used as
+        the relay agent address (<code>giaddr</code>) in relayed DHCP
+        packets.
+      </p>
+      <p>
+        When unset, the primary IPv4 defaults to the first address in
+        <ref column="networks"/> as ordered by OVSDB: the CIDR that
+        sorts first as a string.  This default may not match the
+        intended "primary" address, so on multi-IP ports this option
+        should be set explicitly.  On single-IP ports the only
+        configured address is always used as the primary and the option
+        may be left unset.
+      </p>
+    </column>
+
     <group title="Distributed Gateway Ports">
       <p>
         Gateways, as documented under <code>Gateways</code> in the OVN
diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
index 7d008a8fc..d2ae43819 100644
--- a/tests/ovn-northd.at
+++ b/tests/ovn-northd.at
@@ -13647,6 +13647,82 @@ AT_CAPTURE_FILE([lflows])
 AT_CHECK([grep -e "DHCP_RELAY_" lflows | sed 's/table=../table=??/'], [0], [dnl
 ])
 
+# Multi-IP LRP: re-enable DHCP relay on lrp1 and add a second IPv4
+# network.  options:primary_ipv4 is unset, so ovn-northd falls back
+# to the first address returned by OVSDB - whichever CIDR sorts first
+# as a string.  For ["10.0.0.1/24","192.168.1.1/24"] that is
+# 10.0.0.1/24, so DHCP relay flows are emitted using 10.0.0.1.
+check ovn-nbctl --wait=sb set Logical_Router_port lrp1 dhcp_relay=$dhcp_relay
+check ovn-nbctl --wait=sb set Logical_Router_port lrp1 \
+    'networks=["10.0.0.1/24","192.168.1.1/24"]'
+
+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, 10.0.0.0/24} && ip4.dst == 255.255.255.255 && ip.frag == 0 
&& udp.src == 68 && udp.dst == 67), action=(reg9[[7]] = 
dhcp_relay_req_chk(10.0.0.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 == 10.0.0.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, 10.0.0.0/24} && ip4.dst == 255.255.255.255 && udp.src == 
68 && udp.dst == 67 && reg9[[7]]), action=(ip4.src = 10.0.0.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, 10.0.0.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 == 10.0.0.1 && udp.src == 67 && udp.dst == 67), 
action=(reg2 = ip4.dst; reg9[[8]] = dhcp_relay_resp_chk(10.0.0.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 == 10.0.0.1 && udp.src == 67 && udp.dst == 67 && reg9[[8]]), 
action=(ip4.src = 10.0.0.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 == 10.0.0.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, 10.0.0.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 */)
+])
+
+# Pin the primary IPv4 via options:primary_ipv4.  Every DHCP relay flow
+# should now reference 192.168.1.1/24 instead of 10.0.0.1/24.
+check ovn-nbctl --wait=sb set Logical_Router_port lrp1 \
+    options:primary_ipv4=192.168.1.1
+
+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 */)
+])
+
+# Setting options:primary_ipv4 to an address that does not belong to
+# 'networks' is a misconfiguration: ovn-northd logs a warning and skips
+# DHCP relay flow generation for the port.
+check ovn-nbctl --wait=sb set Logical_Router_port lrp1 \
+    options:primary_ipv4=10.99.99.99
+
+ovn-sbctl lflow-list > lflows
+AT_CAPTURE_FILE([lflows])
+
+AT_CHECK([grep -e "DHCP_RELAY_" lflows | sed 's/table=../table=??/'], [0], [dnl
+])
+AT_CHECK([grep -q "options:primary_ipv4=10.99.99.99 does not match any address 
in 'networks'" northd/ovn-northd.log])
+
+# Reducing 'networks' back to a single IPv4 makes the option no longer
+# mandatory; clearing it should restore DHCP relay flows that reference
+# the remaining address.
+check ovn-nbctl --wait=sb set Logical_Router_port lrp1 \
+    'networks=["10.0.0.1/24"]'
+check ovn-nbctl --wait=sb remove Logical_Router_port lrp1 options primary_ipv4
+
+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, 10.0.0.0/24} && ip4.dst == 255.255.255.255 && ip.frag == 0 
&& udp.src == 68 && udp.dst == 67), action=(reg9[[7]] = 
dhcp_relay_req_chk(10.0.0.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 == 10.0.0.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, 10.0.0.0/24} && ip4.dst == 255.255.255.255 && udp.src == 
68 && udp.dst == 67 && reg9[[7]]), action=(ip4.src = 10.0.0.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, 10.0.0.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 == 10.0.0.1 && udp.src == 67 && udp.dst == 67), 
action=(reg2 = ip4.dst; reg9[[8]] = dhcp_relay_resp_chk(10.0.0.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 == 10.0.0.1 && udp.src == 67 && udp.dst == 67 && reg9[[8]]), 
action=(ip4.src = 10.0.0.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 == 10.0.0.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, 10.0.0.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 */)
+])
+
 OVN_CLEANUP_NORTHD
 AT_CLEANUP
 ])
-- 
2.43.5

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

Reply via email to