Re: [ovs-dev] [PATCH ovn v7 5/6] Support logical switches with multiple localnet ports

2020-05-19 Thread Ihar Hrachyshka

On 5/19/20 10:05 AM, Ihar Hrachyshka wrote:
My understanding is that we assume native C99 _Bool in our compiler 
(not a typedef / macro mapped onto int)



Oh I was too quick to assume that. As per coding-style.rst,


  Also, don't assume that a conversion to ``bool`` or ``_Bool`` follows C99
  semantics, i.e. use ``(bool) (some_value != 0)`` rather than
  ``(bool) some_value``. The latter might produce unexpected results on 
non-C99
  environments. For example, if ``bool`` is implemented as a typedef of 
char

  and ``some_value = 0x1000``.


So we cannot rely on _Bool being a proper C99 boolean, and then your 
suggestion becomes extremely important just from safety perspective! 
Honestly, using booleans *without* C99 semantics is quite dangerous, so 
I'm surprised they are used at all.



TIL. I will push v8 in an hour.


Ihar

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [PATCH ovn v7 5/6] Support logical switches with multiple localnet ports

2020-05-19 Thread Ihar Hrachyshka

On 5/19/20 8:34 AM, Numan Siddique wrote:

On Wed, May 13, 2020 at 7:10 PM Ihar Hrachyshka  wrote:


Assuming only a single localnet port is actually plugged mapped on
each chassis, this allows to maintain disjoint networks plugged to the
same switch.  This is useful to simplify resource management for
OpenStack "routed provider networks" feature [1] where a single
"network" (which traditionally maps to logical switches in OVN) is
comprised of multiple L2 segments and assumes external L3 routing
implemented between the segments.

[1]:
https://docs.openstack.org/ocata/networking-guide/config-routed-networks.html

Signed-off-by: Ihar Hrachyshka 


Hi Ihar,

Please see below. I've 2 small comments.

With the first comment addressed
Acked-by: Numan Siddique 

Since Dumitru has already acked your patches, can you please put an
"Acked-by" tag for Dumitru
and also mine too when you spin up v8.



Thanks for review!

I'll push v8 once I understand the nature of the first request to change 
(see below).





Thanks
Numan


---

  controller/binding.c   |  16 ++
  controller/patch.c |  14 +-
  northd/ovn-northd.c|  62 +++--
  ovn-architecture.7.xml |  50 ++--
  ovn-nb.xml |  23 +-
  ovn-sb.xml |  21 +-
  tests/ovn.at   | 504 +
  7 files changed, 637 insertions(+), 53 deletions(-)

diff --git a/controller/binding.c b/controller/binding.c
index 9d37a23cc..774c6f242 100644
--- a/controller/binding.c
+++ b/controller/binding.c
@@ -683,12 +683,28 @@ add_localnet_egress_interface_mappings(
  }
  }

+static bool
+is_network_plugged(const struct sbrec_port_binding *binding_rec,
+   struct shash *bridge_mappings)
+{
+const char *network = smap_get(&binding_rec->options, "network_name");
+if (!network) {
+return false;
+}
+return shash_find_data(bridge_mappings, network);



shash_find_data returns (void *) and not bool.

I'd suggest to have like

return network ?  !!shash_find_data(bridge_mappings, network) : false;



It's not hard to change that, but I'm slightly puzzled and wonder if I 
miss something in the picture that I should grasp before I adjust the 
code without proper understanding. Let me elaborate.


My understanding is that we assume native C99 _Bool in our compiler (not 
a typedef / macro mapped onto int). If that's the case, AFAIU C99 
standard requires implicit conversion of pointer types to booleans, and 
defines it safely (meaning, a NULL-pointer always maps to false 
regardless of actual representation of the NULL-pointer in memory). 
Considering this, your suggestion seems effectively the same as what is 
already written, just more "traditional" (for example, it would be safer 
in C89 environment). Which particular issue do you think we are to 
tackle here?





+}

+
  static void
  consider_localnet_port(const struct sbrec_port_binding *binding_rec,
 struct shash *bridge_mappings,
 struct sset *egress_ifaces,
 struct hmap *local_datapaths)
  {
+/* Ignore localnet ports for unplugged networks. */
+if (!is_network_plugged(binding_rec, bridge_mappings)) {
+return;
+}
+
  add_localnet_egress_interface_mappings(binding_rec,
  bridge_mappings, egress_ifaces);

diff --git a/controller/patch.c b/controller/patch.c
index 349faae17..7ad30d9cc 100644
--- a/controller/patch.c
+++ b/controller/patch.c
@@ -198,8 +198,10 @@ add_bridge_mappings(struct ovsdb_idl_txn *ovs_idl_txn,
  continue;
  }

+bool is_localnet = false;
  const char *patch_port_id;
  if (!strcmp(binding->type, "localnet")) {
+is_localnet = true;
  patch_port_id = "ovn-localnet-port";
  } else if (!strcmp(binding->type, "l2gateway")) {
  if (!binding->chassis
@@ -224,9 +226,15 @@ add_bridge_mappings(struct ovsdb_idl_txn *ovs_idl_txn,
  struct ovsrec_bridge *br_ln = shash_find_data(&bridge_mappings,
network);
  if (!br_ln) {
  static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
-VLOG_ERR_RL(&rl, "bridge not found for %s port '%s' "
-"with network name '%s'",
-binding->type, binding->logical_port, network);
+if (!is_localnet) {
+VLOG_ERR_RL(&rl, "bridge not found for %s port '%s' "
+"with network name '%s'",
+binding->type, binding->logical_port, network);
+} else {
+VLOG_INFO_RL(&rl, "bridge not found for localnet port
'%s' "
+"with network name '%s'; skipping",
+binding->logical_port, network);
+}
  continue;
  }

diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
index 5e7796c5b..2308b10e6 100644
--- a/northd/ovn-northd.c
+++ b/northd/ovn-northd.c
@@ -543,7 +54

Re: [ovs-dev] [PATCH ovn v7 5/6] Support logical switches with multiple localnet ports

2020-05-19 Thread Numan Siddique
On Wed, May 13, 2020 at 7:10 PM Ihar Hrachyshka  wrote:

> Assuming only a single localnet port is actually plugged mapped on
> each chassis, this allows to maintain disjoint networks plugged to the
> same switch.  This is useful to simplify resource management for
> OpenStack "routed provider networks" feature [1] where a single
> "network" (which traditionally maps to logical switches in OVN) is
> comprised of multiple L2 segments and assumes external L3 routing
> implemented between the segments.
>
> [1]:
> https://docs.openstack.org/ocata/networking-guide/config-routed-networks.html
>
> Signed-off-by: Ihar Hrachyshka 
>

Hi Ihar,

Please see below. I've 2 small comments.

With the first comment addressed
Acked-by: Numan Siddique 

Since Dumitru has already acked your patches, can you please put an
"Acked-by" tag for Dumitru
and also mine too when you spin up v8.

Thanks
Numan


---
>  controller/binding.c   |  16 ++
>  controller/patch.c |  14 +-
>  northd/ovn-northd.c|  62 +++--
>  ovn-architecture.7.xml |  50 ++--
>  ovn-nb.xml |  23 +-
>  ovn-sb.xml |  21 +-
>  tests/ovn.at   | 504 +
>  7 files changed, 637 insertions(+), 53 deletions(-)
>
> diff --git a/controller/binding.c b/controller/binding.c
> index 9d37a23cc..774c6f242 100644
> --- a/controller/binding.c
> +++ b/controller/binding.c
> @@ -683,12 +683,28 @@ add_localnet_egress_interface_mappings(
>  }
>  }
>
> +static bool
> +is_network_plugged(const struct sbrec_port_binding *binding_rec,
> +   struct shash *bridge_mappings)
> +{
> +const char *network = smap_get(&binding_rec->options, "network_name");
> +if (!network) {
> +return false;
> +}
> +return shash_find_data(bridge_mappings, network);
>


shash_find_data returns (void *) and not bool.

I'd suggest to have like

return network ?  !!shash_find_data(bridge_mappings, network) : false;


+}
> +
>  static void
>  consider_localnet_port(const struct sbrec_port_binding *binding_rec,
> struct shash *bridge_mappings,
> struct sset *egress_ifaces,
> struct hmap *local_datapaths)
>  {
> +/* Ignore localnet ports for unplugged networks. */
> +if (!is_network_plugged(binding_rec, bridge_mappings)) {
> +return;
> +}
> +
>  add_localnet_egress_interface_mappings(binding_rec,
>  bridge_mappings, egress_ifaces);
>
> diff --git a/controller/patch.c b/controller/patch.c
> index 349faae17..7ad30d9cc 100644
> --- a/controller/patch.c
> +++ b/controller/patch.c
> @@ -198,8 +198,10 @@ add_bridge_mappings(struct ovsdb_idl_txn *ovs_idl_txn,
>  continue;
>  }
>
> +bool is_localnet = false;
>  const char *patch_port_id;
>  if (!strcmp(binding->type, "localnet")) {
> +is_localnet = true;
>  patch_port_id = "ovn-localnet-port";
>  } else if (!strcmp(binding->type, "l2gateway")) {
>  if (!binding->chassis
> @@ -224,9 +226,15 @@ add_bridge_mappings(struct ovsdb_idl_txn *ovs_idl_txn,
>  struct ovsrec_bridge *br_ln = shash_find_data(&bridge_mappings,
> network);
>  if (!br_ln) {
>  static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
> -VLOG_ERR_RL(&rl, "bridge not found for %s port '%s' "
> -"with network name '%s'",
> -binding->type, binding->logical_port, network);
> +if (!is_localnet) {
> +VLOG_ERR_RL(&rl, "bridge not found for %s port '%s' "
> +"with network name '%s'",
> +binding->type, binding->logical_port, network);
> +} else {
> +VLOG_INFO_RL(&rl, "bridge not found for localnet port
> '%s' "
> +"with network name '%s'; skipping",
> +binding->logical_port, network);
> +}
>  continue;
>  }
>
> diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
> index 5e7796c5b..2308b10e6 100644
> --- a/northd/ovn-northd.c
> +++ b/northd/ovn-northd.c
> @@ -543,7 +543,9 @@ struct ovn_datapath {
>  /* The "derived" OVN port representing the instance of l3dgw_port on
>   * the "redirect-chassis". */
>  struct ovn_port *l3redirect_port;
> -struct ovn_port *localnet_port;
> +
> +struct ovn_port **localnet_ports;
> +size_t n_localnet_ports;
>
>  struct ovs_list lr_list; /* In list of logical router datapaths. */
>  /* The logical router group to which this datapath belongs.
> @@ -611,6 +613,7 @@ ovn_datapath_destroy(struct hmap *datapaths, struct
> ovn_datapath *od)
>  ovn_destroy_tnlids(&od->port_tnlids);
>  bitmap_free(od->ipam_info.allocated_ipv4s);
>  free(od->router_ports);
> +free(od->localnet_ports);
>  ovn_ls_port_group_destroy(&od->nb_pgs);
>  destroy_mcast

[ovs-dev] [PATCH ovn v7 5/6] Support logical switches with multiple localnet ports

2020-05-13 Thread Ihar Hrachyshka
Assuming only a single localnet port is actually plugged mapped on
each chassis, this allows to maintain disjoint networks plugged to the
same switch.  This is useful to simplify resource management for
OpenStack "routed provider networks" feature [1] where a single
"network" (which traditionally maps to logical switches in OVN) is
comprised of multiple L2 segments and assumes external L3 routing
implemented between the segments.

[1]: 
https://docs.openstack.org/ocata/networking-guide/config-routed-networks.html

Signed-off-by: Ihar Hrachyshka 
---
 controller/binding.c   |  16 ++
 controller/patch.c |  14 +-
 northd/ovn-northd.c|  62 +++--
 ovn-architecture.7.xml |  50 ++--
 ovn-nb.xml |  23 +-
 ovn-sb.xml |  21 +-
 tests/ovn.at   | 504 +
 7 files changed, 637 insertions(+), 53 deletions(-)

diff --git a/controller/binding.c b/controller/binding.c
index 9d37a23cc..774c6f242 100644
--- a/controller/binding.c
+++ b/controller/binding.c
@@ -683,12 +683,28 @@ add_localnet_egress_interface_mappings(
 }
 }
 
+static bool
+is_network_plugged(const struct sbrec_port_binding *binding_rec,
+   struct shash *bridge_mappings)
+{
+const char *network = smap_get(&binding_rec->options, "network_name");
+if (!network) {
+return false;
+}
+return shash_find_data(bridge_mappings, network);
+}
+
 static void
 consider_localnet_port(const struct sbrec_port_binding *binding_rec,
struct shash *bridge_mappings,
struct sset *egress_ifaces,
struct hmap *local_datapaths)
 {
+/* Ignore localnet ports for unplugged networks. */
+if (!is_network_plugged(binding_rec, bridge_mappings)) {
+return;
+}
+
 add_localnet_egress_interface_mappings(binding_rec,
 bridge_mappings, egress_ifaces);
 
diff --git a/controller/patch.c b/controller/patch.c
index 349faae17..7ad30d9cc 100644
--- a/controller/patch.c
+++ b/controller/patch.c
@@ -198,8 +198,10 @@ add_bridge_mappings(struct ovsdb_idl_txn *ovs_idl_txn,
 continue;
 }
 
+bool is_localnet = false;
 const char *patch_port_id;
 if (!strcmp(binding->type, "localnet")) {
+is_localnet = true;
 patch_port_id = "ovn-localnet-port";
 } else if (!strcmp(binding->type, "l2gateway")) {
 if (!binding->chassis
@@ -224,9 +226,15 @@ add_bridge_mappings(struct ovsdb_idl_txn *ovs_idl_txn,
 struct ovsrec_bridge *br_ln = shash_find_data(&bridge_mappings, 
network);
 if (!br_ln) {
 static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
-VLOG_ERR_RL(&rl, "bridge not found for %s port '%s' "
-"with network name '%s'",
-binding->type, binding->logical_port, network);
+if (!is_localnet) {
+VLOG_ERR_RL(&rl, "bridge not found for %s port '%s' "
+"with network name '%s'",
+binding->type, binding->logical_port, network);
+} else {
+VLOG_INFO_RL(&rl, "bridge not found for localnet port '%s' "
+"with network name '%s'; skipping",
+binding->logical_port, network);
+}
 continue;
 }
 
diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
index 5e7796c5b..2308b10e6 100644
--- a/northd/ovn-northd.c
+++ b/northd/ovn-northd.c
@@ -543,7 +543,9 @@ struct ovn_datapath {
 /* The "derived" OVN port representing the instance of l3dgw_port on
  * the "redirect-chassis". */
 struct ovn_port *l3redirect_port;
-struct ovn_port *localnet_port;
+
+struct ovn_port **localnet_ports;
+size_t n_localnet_ports;
 
 struct ovs_list lr_list; /* In list of logical router datapaths. */
 /* The logical router group to which this datapath belongs.
@@ -611,6 +613,7 @@ ovn_datapath_destroy(struct hmap *datapaths, struct 
ovn_datapath *od)
 ovn_destroy_tnlids(&od->port_tnlids);
 bitmap_free(od->ipam_info.allocated_ipv4s);
 free(od->router_ports);
+free(od->localnet_ports);
 ovn_ls_port_group_destroy(&od->nb_pgs);
 destroy_mcast_info_for_datapath(od);
 
@@ -2025,6 +2028,7 @@ join_logical_ports(struct northd_context *ctx,
 struct ovn_datapath *od;
 HMAP_FOR_EACH (od, key_node, datapaths) {
 if (od->nbs) {
+size_t allocated_localnet_ports = 0;
 for (size_t i = 0; i < od->nbs->n_ports; i++) {
 const struct nbrec_logical_switch_port *nbsp
 = od->nbs->ports[i];
@@ -2059,7 +2063,12 @@ join_logical_ports(struct northd_context *ctx,
 }
 
 if (!strcmp(nbsp->type, "localnet")) {
-   od->localnet_port = op;
+   if (od->n_localnet_ports >= allocated_localnet_ports) {
+