On 9 May 2016 at 23:57, Mickey Spiegel <[email protected]> wrote:

> The big issue for me is your last comment:
>
> If you add bob2 on hv1, would bob2 be able to reach alice1?
>
>                  No; take foo1 which is already on hv1 for this example;
> if I try to send b/w foo1 and alice1, I have “no route to alice1, the
> destination” because all I can use on hv1 is R1 routes. If I change the
> test with new permissive catchall routes everywhere, I could do it, of
> course, but that is something else and contrary to what you would want to
> do.
>
>
> There is a reason that I mentioned bob rather than foo.
>
> The logical connectivity is
> bob -- R1 -- foo
> and
> bob -- R2 -- alice
>
> Since there are no static routes configured between R1 and R2, foo has no
> logical connectivity to alice.
>
> There *is* logical connectivity between bob and alice through R2.
>
> With your code, you get different behavior depending on whether the
> endpoint in bob is on hv1 or hv2.
> Since bob1 and alice1 are both on hv2 along with R2, bob1 can reach alice1.
> If you add bob2 on hv1, bob2 cannot reach alice1.
>
> Why should you get different connectivity depending on placement of
> endpoints within logical switch bob?
> If bob is connected to R2, any endpoint anywhere in bob should be able to
> reach R2, and continue on to any endpoints in other logical switches (i.e.
> alice) connected to R2.
>
> Cutting the patch port as you did in v3 is not enough. Unless you restrict
> bob to the same subset of chassis as R2, I would think what you really want
> is to associate the patch port's port binding with hv2. If you do that,
> then on hv1, physical.c would add an entry in table 32 for datapath bob
> that would direct traffic to the patch port down a tunnel to hv2.
>
> This seems like it would be a lot simpler if each "local router" is
> limited to only one chassis. If a "local router" can be on multiple
> chassis, I start thinking about multiple possible chassis and ECMP which
> would add significant complexity.
>



Before this discussion goes too far, I would like to point out that I have
done something similar to what Mickey is suggesting here for the l3 gateway
work. I sent a patch here:
http://openvswitch.org/pipermail/dev/2016-May/070790.html

I will send the DNAT and SNAT implementations on top of the above patch
either today evening or tomorrow (unless I hit some new bugs). But
specifically for DNAT and SNAT, we want the router pipeline's ingress and
egress to happen on the same host.


>
> Mickey
>
>
> -----Darrell Ball <[email protected]> wrote: -----
> To: Mickey Spiegel/San Jose/IBM@IBMUS
> From: Darrell Ball <[email protected]>
> Date: 05/09/2016 09:11PM
> Cc: [email protected]
> Subject: Re: [ovs-dev] [patch_v1] ovn: add local router support (RFC)
>
>
>
> On Mon, May 9, 2016 at 4:40 PM, Mickey Spiegel <[email protected]>
> wrote:
> I am missing something basic here.
>
> In your tests, you have logical switch bob that seems like it could be
> present on both hv1 and hv2, and a logical router R2 that is local to hv2
> but not present on hv1.
>
>                  Exactly
>
>  Wouldn't the logical switch bob flows on hv1 still send packets locally
> to the patch port rp-bob?
> But when the packets come back around to logical router R2 flows, they are
> not present on hv1?
>
>                  Exactly; I don’t want R2 flows processed and downloaded
> on HV1.
>
>
>
>  Don't you need to change the patch ports so that they are not considered
> local if the associated logical router is not local to this chassis?
>
>                  Its not required.
>   The router<->switch patch cabling is still there.
>   I did not “cut the cable” as it were; I enabled selective router flow
> processing and download in this patch. The idea is to not process and
> download flows that are not needed on a given HV.
>
>   Its probably fine to also “cut the patch cable” for the router to
> switch. Its pretty cheap to do that in a minimal way, so I added it for
> now. I really want to keep it as simple as possible and not add unnecessary
> code, however.
>
>
>
> If you add bob2 on hv1, would bob2 be able to reach alice1?
>
>                  No; take foo1 which is already on hv1 for this example;
> if I try to send b/w foo1 and alice1, I have “no route to alice1, the
> destination” because all I can use on hv1 is R1 routes. If I change the
> test with new permissive catchall routes everywhere, I could do it, of
> course, but that is something else and contrary to what you would want to
> do.
>
>
>
> Mickey
>
>
> -----"dev" <[email protected]> wrote: -----
> To: [email protected], [email protected]
> From: Darrell Ball
> Sent by: "dev"
> Date: 05/09/2016 11:58AM
> Subject: [ovs-dev] [patch_v1] ovn: add local router support (RFC)
>
> This patch adds local router support. A logical router can
> be declared local at northbound level via external_ids.
> This is communicated to the southbound database via northd
> which populates the external_id of the datapath_binding table.
> ovn-controller will also allow a chassis to be configured for 1 or
> more local routers.
> When ovn-controller configures openflow rules it looks at whether
> a logical router is local and it so it checks where its chassis
> instance local routers has this particular logical router configured
> as local; if it does, it allows the southbound flows of the local
> logical router to be translated into openflow rules and programmed
> on this chassis.  If a logical router is labelled as local but a
> given chassis is not configured for that logical router to be local,
> then the corresponding openflow rules are not programmed on this
> chassis.
>
> Signed-off-by: Darrell Ball <[email protected]>
> ---
>  ovn/controller/chassis.c            |  32 +++++-
>  ovn/controller/chassis.h            |   4 +-
>  ovn/controller/lflow.c              |  16 ++-
>  ovn/controller/lflow.h              |   4 +-
>  ovn/controller/ovn-controller.8.xml |   8 ++
>  ovn/controller/ovn-controller.c     |  50 +++++++++-
>  ovn/controller/ovn-controller.h     |   4 +
>  ovn/northd/ovn-northd.c             |  17 +++-
>  ovn/ovn-nb.xml                      |   6 +-
>  ovn/ovn-sb.xml                      |   8 ++
>  tests/ovn.at                        | 189
> ++++++++++++++++++++++++++++++++++++
>  11 files changed, 324 insertions(+), 14 deletions(-)
>
> diff --git a/ovn/controller/chassis.c b/ovn/controller/chassis.c
> index d40181b..e58145b 100644
> --- a/ovn/controller/chassis.c
> +++ b/ovn/controller/chassis.c
> @@ -24,6 +24,7 @@
>  #include "openvswitch/vlog.h"
>  #include "ovn/lib/ovn-sb-idl.h"
>  #include "ovn-controller.h"
> +#include "sset.h"
>
>  VLOG_DEFINE_THIS_MODULE(chassis);
>
> @@ -63,8 +64,16 @@ get_bridge_mappings(const struct smap *ext_ids)
>      return bridge_mappings ? bridge_mappings : "";
>  }
>
> +static const char *
> +get_local_routers(const struct smap *ext_ids)
> +{
> +    const char *local_routers = smap_get(ext_ids, "local-routers");
> +    return local_routers ? local_routers : "";
> +}
> +
>  void
> -chassis_run(struct controller_ctx *ctx, const char *chassis_id)
> +chassis_run(struct controller_ctx *ctx, const char *chassis_id,
> +            struct sset *local_router_datapaths)
>  {
>      if (!ctx->ovnsb_idl_txn) {
>          return;
> @@ -112,6 +121,8 @@ chassis_run(struct controller_ctx *ctx, const char
> *chassis_id)
>
>      const char *bridge_mappings = get_bridge_mappings(&cfg->external_ids);
>
> +    const char *local_routers = get_local_routers(&cfg->external_ids);
> +
>      const struct sbrec_chassis *chassis_rec
>          = get_chassis(ctx->ovnsb_idl, chassis_id);
>
> @@ -131,6 +142,17 @@ chassis_run(struct controller_ctx *ctx, const char
> *chassis_id)
>              smap_destroy(&new_ids);
>          }
>
> +        const char *chassis_local_routers
> +            = get_local_routers(&chassis_rec->external_ids);
> +        if (strcmp(local_routers, chassis_local_routers)) {
> +            struct smap new_ids;
> +            smap_clone(&new_ids, &chassis_rec->external_ids);
> +            smap_replace(&new_ids, "local-router", local_routers);
> +            sbrec_chassis_verify_external_ids(chassis_rec);
> +            sbrec_chassis_set_external_ids(chassis_rec, &new_ids);
> +            smap_destroy(&new_ids);
> +        }
> +
>          /* Compare desired tunnels against those currently in the
> database. */
>          uint32_t cur_tunnels = 0;
>          bool same = true;
> @@ -166,12 +188,16 @@ chassis_run(struct controller_ctx *ctx, const char
> *chassis_id)
>                                chassis_id);
>
>      if (!chassis_rec) {
> -        struct smap ext_ids = SMAP_CONST1(&ext_ids, "ovn-bridge-mappings",
> -                                          bridge_mappings);
> +
> +        struct smap ext_ids = SMAP_INITIALIZER(&ext_ids);
> +        smap_add(&ext_ids, "ovn-bridge-mappings",
> +                 bridge_mappings);
> +        smap_add(&ext_ids, "local-routers", local_routers);
>          chassis_rec = sbrec_chassis_insert(ctx->ovnsb_idl_txn);
>          sbrec_chassis_set_name(chassis_rec, chassis_id);
>          sbrec_chassis_set_hostname(chassis_rec, hostname);
>          sbrec_chassis_set_external_ids(chassis_rec, &ext_ids);
> +        smap_destroy(&ext_ids);
>      }
>
>      int n_encaps = count_1bits(req_tunnels);
> diff --git a/ovn/controller/chassis.h b/ovn/controller/chassis.h
> index 26017d0..324e3cf 100644
> --- a/ovn/controller/chassis.h
> +++ b/ovn/controller/chassis.h
> @@ -21,9 +21,11 @@
>  struct controller_ctx;
>  struct ovsdb_idl;
>  struct ovsrec_bridge;
> +struct sset;
>
>  void chassis_register_ovs_idl(struct ovsdb_idl *);
> -void chassis_run(struct controller_ctx *, const char *chassis_id);
> +void chassis_run(struct controller_ctx *, const char *chassis_id,
> +                 struct sset *);
>  bool chassis_cleanup(struct controller_ctx *, const char *chassis_id);
>
>  #endif /* ovn/chassis.h */
> diff --git a/ovn/controller/lflow.c b/ovn/controller/lflow.c
> index 96b7c66..d86646a 100644
> --- a/ovn/controller/lflow.c
> +++ b/ovn/controller/lflow.c
> @@ -199,7 +199,8 @@ add_logical_flows(struct controller_ctx *ctx, const
> struct lport_index *lports,
>                    const struct mcgroup_index *mcgroups,
>                    const struct hmap *local_datapaths,
>                    const struct hmap *patched_datapaths,
> -                  const struct simap *ct_zones, struct hmap *flow_table)
> +                  const struct simap *ct_zones, struct hmap *flow_table,
> +                                  const struct sset *local_routers)
>  {
>      uint32_t conj_id_ofs = 1;
>
> @@ -250,6 +251,13 @@ add_logical_flows(struct controller_ctx *ctx, const
> struct lport_index *lports,
>                      continue;
>                  }
>              }
> +        } else {
> +            const char *local_router =
> +                smap_get(&ldp->external_ids, "local-router");
> +            if (strcmp(local_router, "") &&
> +                !is_local_router(local_routers, local_router)) {
> +                continue;
> +            }
>          }
>
>          /* Determine translation of logical table IDs to physical table
> IDs. */
> @@ -429,10 +437,12 @@ lflow_run(struct controller_ctx *ctx, const struct
> lport_index *lports,
>            const struct mcgroup_index *mcgroups,
>            const struct hmap *local_datapaths,
>            const struct hmap *patched_datapaths,
> -          const struct simap *ct_zones, struct hmap *flow_table)
> +          const struct simap *ct_zones, struct hmap *flow_table,
> +                  const struct sset *local_router_datapaths)
>  {
>      add_logical_flows(ctx, lports, mcgroups, local_datapaths,
> -                      patched_datapaths, ct_zones, flow_table);
> +                      patched_datapaths, ct_zones, flow_table,
> +                      local_router_datapaths);
>      add_neighbor_flows(ctx, lports, flow_table);
>  }
>
> diff --git a/ovn/controller/lflow.h b/ovn/controller/lflow.h
> index a3fc50c..4144481 100644
> --- a/ovn/controller/lflow.h
> +++ b/ovn/controller/lflow.h
> @@ -41,6 +41,7 @@ struct lport_index;
>  struct mcgroup_index;
>  struct simap;
>  struct uuid;
> +struct sset;
>
>  /* OpenFlow table numbers.
>   *
> @@ -64,7 +65,8 @@ void lflow_run(struct controller_ctx *, const struct
> lport_index *,
>                 const struct hmap *local_datapaths,
>                 const struct hmap *patched_datapaths,
>                 const struct simap *ct_zones,
> -               struct hmap *flow_table);
> +               struct hmap *flow_table,
> +                           const struct sset *local_routers);
>  void lflow_destroy(void);
>
>  #endif /* ovn/lflow.h */
> diff --git a/ovn/controller/ovn-controller.8.xml
> b/ovn/controller/ovn-controller.8.xml
> index 1ee3a6e..582a00b 100644
> --- a/ovn/controller/ovn-controller.8.xml
> +++ b/ovn/controller/ovn-controller.8.xml
> @@ -154,6 +154,14 @@
>          value mapping two physical network names to two ovs bridges would
> be:
>          <code>physnet1:br-eth0,physnet2:br-eth1</code>.
>        </dd>
> +      <dt><code>external_ids:local-routers</code></dt>
> +      <dd>
> +        A set of a local routers on this chassis instance. The logical
> flows of a
> +        local logical router datapath are only translated into openflow
> +        flows if the chassis is configured for that local logical router.
> +        An example set with two local routers would be:
> +        <code>local_router_1,local_router_2</code>.
> +      </dd>
>      </dl>
>
>      <h1>Open vSwitch Database Usage</h1>
> diff --git a/ovn/controller/ovn-controller.c
> b/ovn/controller/ovn-controller.c
> index f68f842..e6c390a 100644
> --- a/ovn/controller/ovn-controller.c
> +++ b/ovn/controller/ovn-controller.c
> @@ -51,6 +51,7 @@
>  #include "stream.h"
>  #include "unixctl.h"
>  #include "util.h"
> +#include "sset.h"
>
>  VLOG_DEFINE_THIS_MODULE(main);
>
> @@ -252,6 +253,37 @@ get_ovnsb_remote_probe_interval(struct ovsdb_idl
> *ovs_idl, int *value)
>      return false;
>  }
>
> +bool is_local_router(const struct sset *local_routers,
> +                     const char *local_router)
> +{
> +    if (sset_find(local_routers, local_router)) {
> +        return true;
> +    }
> +    return false;
> +}
> +
> +static void
> +build_local_routers(const struct smap *ext_ids,
> +                    struct sset *local_routers)
> +{
> +        const char *local_router_cfg = smap_get(ext_ids, "local-routers");
> +    if (!local_router_cfg) {
> +        local_router_cfg = "";
> +    }
> +
> +    char *cur, *next, *start;
> +    next = start = xstrdup(local_router_cfg);
> +    while ((cur = strsep(&next, ",")) && *cur) {
> +        char *local_router = cur;
> +
> +        if (sset_find(local_routers, local_router)) {
> +            continue;
> +        }
> +        sset_add(local_routers, local_router);
> +    }
> +    free(start);
> +}
> +
>  int
>  main(int argc, char *argv[])
>  {
> @@ -353,11 +385,22 @@ main(int argc, char *argv[])
>
>          struct hmap patched_datapaths =
> HMAP_INITIALIZER(&patched_datapaths);
>
> +        struct sset local_routers =
> +            SSET_INITIALIZER(&local_routers);
> +
>          const struct ovsrec_bridge *br_int = get_br_int(&ctx);
>          const char *chassis_id = get_chassis_id(ctx.ovs_idl);
>
>          if (chassis_id) {
> -            chassis_run(&ctx, chassis_id);
> +            chassis_run(&ctx, chassis_id, &local_routers);
> +
> +            const struct sbrec_chassis *chassis_rec =
> +                get_chassis(ctx.ovnsb_idl, chassis_id);
> +            if (chassis_rec) {
> +                build_local_routers(&chassis_rec->external_ids,
> +                                    &local_routers);
> +            }
> +
>              encaps_run(&ctx, br_int, chassis_id);
>              binding_run(&ctx, br_int, chassis_id, &ct_zones,
> ct_zone_bitmap,
>                      &local_datapaths);
> @@ -377,7 +420,8 @@ main(int argc, char *argv[])
>
>              struct hmap flow_table = HMAP_INITIALIZER(&flow_table);
>              lflow_run(&ctx, &lports, &mcgroups, &local_datapaths,
> -                      &patched_datapaths, &ct_zones, &flow_table);
> +                      &patched_datapaths, &ct_zones, &flow_table,
> +                      &local_routers);
>              if (chassis_id) {
>                  physical_run(&ctx, mff_ovn_geneve,
>                               br_int, chassis_id, &ct_zones, &flow_table,
> @@ -404,6 +448,8 @@ main(int argc, char *argv[])
>          }
>          hmap_destroy(&patched_datapaths);
>
> +        sset_destroy(&local_routers);
> +
>          unixctl_server_run(unixctl);
>
>          unixctl_server_wait(unixctl);
> diff --git a/ovn/controller/ovn-controller.h
> b/ovn/controller/ovn-controller.h
> index 9af7959..012560c 100644
> --- a/ovn/controller/ovn-controller.h
> +++ b/ovn/controller/ovn-controller.h
> @@ -23,6 +23,7 @@
>  /* Linux supports a maximum of 64K zones, which seems like a fine
> default. */
>  #define MAX_CT_ZONES 65535
>
> +struct sset;
>  struct controller_ctx {
>      struct ovsdb_idl *ovnsb_idl;
>      struct ovsdb_idl_txn *ovnsb_idl_txn;
> @@ -53,6 +54,9 @@ struct patched_datapath {
>  struct patched_datapath *get_patched_datapath(const struct hmap *,
>                                                uint32_t tunnel_key);
>
> +bool is_local_router(const struct sset *local_routers,
> +                     const char *local_router);
> +
>  const struct ovsrec_bridge *get_bridge(struct ovsdb_idl *,
>                                         const char *br_name);
>
> diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c
> index 9e03606..b271f7f 100644
> --- a/ovn/northd/ovn-northd.c
> +++ b/ovn/northd/ovn-northd.c
> @@ -460,8 +460,21 @@ build_datapaths(struct northd_context *ctx, struct
> hmap *datapaths)
>              char uuid_s[UUID_LEN + 1];
>              sprintf(uuid_s, UUID_FMT, UUID_ARGS(&od->key));
>              const char *key = od->nbs ? "logical-switch" :
> "logical-router";
> -            const struct smap id = SMAP_CONST1(&id, key, uuid_s);
> -            sbrec_datapath_binding_set_external_ids(od->sb, &id);
> +            struct smap ids = SMAP_INITIALIZER(&ids);
> +            smap_add(&ids, key, uuid_s);
> +
> +            if (od->nbr) {
> +                const char *value = smap_get(&od->nbr->external_ids,
> +                                             "local-router");
> +
> +                if (value) {
> +                    smap_add(&ids, "local-router", value);
> +                } else {
> +                    smap_add(&ids, "local-router", "");
> +                }
> +            }
> +            sbrec_datapath_binding_set_external_ids(od->sb, &ids);
> +            smap_destroy(&ids);
>
>              sbrec_datapath_binding_set_tunnel_key(od->sb, tunnel_key);
>          }
> diff --git a/ovn/ovn-nb.xml b/ovn/ovn-nb.xml
> index 34251af..5b84d6c 100644
> --- a/ovn/ovn-nb.xml
> +++ b/ovn/ovn-nb.xml
> @@ -639,8 +639,10 @@
>      </column>
>
>      <group title="Common Columns">
> -      <column name="external_ids">
> -        See <em>External IDs</em> at the beginning of this document.
> +      <column name="external_ids" key="local-router">
> +        The CMS populates this optional key with the a local router name,
> which
> +        <code>ovn-northd</code> writes into the southbound database
> +        <code>datapath_binding</code> table.
>        </column>
>      </group>
>    </table>
> diff --git a/ovn/ovn-sb.xml b/ovn/ovn-sb.xml
> index efd2f9a..aa0d8bd 100644
> --- a/ovn/ovn-sb.xml
> +++ b/ovn/ovn-sb.xml
> @@ -1189,6 +1189,14 @@ tcp.flags = RST;
>          corresponding <ref table="Logical_Router" db="OVN_Northbound"/>
> row in
>          the <ref db="OVN_Northbound"/> database.
>        </column>
> +
> +      <column name="external_ids" key="local-router">
> +        <code>ovn-northd</code> populates this key with the a local
> router name,
> +        which <code>ovn-northd</code> reads from the corresponding logical
> +        router in the northbound database.  The use of this external_id is
> +        optional.
> +      </column>
> +
>      </group>
>
>      <group title="Common Columns">
> diff --git a/tests/ovn.at b/tests/ovn.at
> index 173dc27..b7b3ad5 100644
> --- a/tests/ovn.at
> +++ b/tests/ovn.at
> @@ -2748,3 +2748,192 @@ OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])
>  OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>
>  AT_CLEANUP
> +
> +AT_SETUP([ovn -- 2 HVs, 3 LS, 1 lport/LS, 2 peer LRs, local router])
> +AT_KEYWORDS([ovnlocalrouter])
> +AT_SKIP_IF([test $HAVE_PYTHON = no])
> +ovn_start
> +
> +# Logical network:
> +# Two LRs - R1 and R2 that are connected to each other as peers in
> 20.0.0.0/24
> +# network. R1 has switch foo (192.168.1.0/24) connected to it.
> +# R2 has alice (172.16.1.0/24) and bob (172.16.2.0/24) connected to it.
> +
> +ovn-nbctl create Logical_Router name=R1
> +ovn-nbctl create Logical_Router name=R2 external-ids:local-router=llr2
> +
> +ovn-nbctl lswitch-add foo
> +ovn-nbctl lswitch-add alice
> +ovn-nbctl lswitch-add bob
> +
> +# Connect foo to R1
> +ovn-nbctl -- --id=@lrp create Logical_Router_port name=foo \
> +network=192.168.1.1/24 mac=\"00:00:00:01:02:03\" -- add Logical_Router
> R1 \
> +ports @lrp -- lport-add foo rp-foo
> +
> +ovn-nbctl set Logical_port rp-foo type=router options:router-port=foo \
> +addresses=\"00:00:00:01:02:03\"
> +
> +# Connect alice to R2
> +ovn-nbctl -- --id=@lrp create Logical_Router_port name=alice \
> +network=172.16.1.1/24 mac=\"00:00:00:01:02:04\" -- add Logical_Router R2
> \
> +ports @lrp -- lport-add alice rp-alice
> +
> +ovn-nbctl set Logical_port rp-alice type=router options:router-port=alice
> \
> +addresses=\"00:00:00:01:02:04\"
> +
> +# Connect bob to R1
> +ovn-nbctl -- --id=@lrp create Logical_Router_port name=bob-r1 \
> +network=172.16.2.3/24 mac=\"00:00:00:01:02:06\" -- add Logical_Router R1
> \
> +ports @lrp -- lport-add bob rp-bob-r1
> +
> +ovn-nbctl set Logical_port rp-bob-r1 type=router
> options:router-port=bob-r1 \
> +addresses=\"00:00:00:01:02:06\"
> +
> +# Connect bob to R2
> +ovn-nbctl -- --id=@lrp create Logical_Router_port name=bob \
> +network=172.16.2.1/24 mac=\"00:00:00:01:02:05\" -- add Logical_Router R2
> \
> +ports @lrp -- lport-add bob rp-bob
> +
> +ovn-nbctl set Logical_port rp-bob type=router options:router-port=bob \
> +addresses=\"00:00:00:01:02:05\"
> +
> +# Create logical port foo1 in foo
> +ovn-nbctl lport-add foo foo1 \
> +-- lport-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
> +
> +# Create logical port alice1 in alice
> +ovn-nbctl lport-add alice alice1 \
> +-- lport-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.2"
> +
> +# Create logical port bob1 in bob
> +ovn-nbctl lport-add bob bob1 \
> +-- lport-set-addresses bob1 "f0:00:00:01:02:05 172.16.2.2"
> +
> +# Create two hypervisor and create OVS ports corresponding to logical
> ports.
> +net_add n1
> +
> +sim_add hv1
> +as hv1
> +ovs-vsctl add-br br-phys
> +ovn_attach n1 br-phys 192.168.0.1
> +ovs-vsctl -- add-port br-int hv1-vif1 -- \
> +    set interface hv1-vif1 external-ids:iface-id=foo1 \
> +    options:tx_pcap=hv1/vif1-tx.pcap \
> +    options:rxq_pcap=hv1/vif1-rx.pcap \
> +    ofport-request=1
> +
> +
> +sim_add hv2
> +as hv2
> +ovs-vsctl add-br br-phys
> +ovs-vsctl set open . external-ids:local-routers=llr2
> +ovn_attach n1 br-phys 192.168.0.2
> +ovs-vsctl -- add-port br-int hv2-vif1 -- \
> +    set interface hv2-vif1 external-ids:iface-id=bob1 \
> +    options:tx_pcap=hv2/vif1-tx.pcap \
> +    options:rxq_pcap=hv2/vif1-rx.pcap \
> +    ofport-request=1
> +
> +ovs-vsctl -- add-port br-int hv2-vif2 -- \
> +    set interface hv2-vif2 external-ids:iface-id=alice1 \
> +    options:tx_pcap=hv2/vif2-tx.pcap \
> +    options:rxq_pcap=hv2/vif2-rx.pcap \
> +    ofport-request=2
> +
> +
> +# Pre-populate the hypervisors' ARP tables so that we don't lose any
> +# packets for ARP resolution (native tunneling doesn't queue packets
> +# for ARP resolution).
> +ovn_populate_arp
> +
> +# Allow some time for ovn-northd and ovn-controller to catch up.
> +# XXX This should be more systematic.
> +sleep 1
> +
> +ip_to_hex() {
> +    printf "%02x%02x%02x%02x" "$@"
> +}
> +trim_zeros() {
> +    sed 's/\(00\)\{1,\}$//'
> +}
> +
> +# Send ip packets between foo1 and bob1
> +src_mac="f00000010203"
> +dst_mac="000000010203"
> +src_ip=`ip_to_hex 192 168 1 2`
> +dst_ip=`ip_to_hex 172 16 2 2`
>
> +packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
> +as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
> +
> +# Send ip packets between bob1 and alice1
> +src_mac="f00000010205"
> +dst_mac="000000010205"
> +src_ip=`ip_to_hex 172 16 2 2`
> +dst_ip=`ip_to_hex 172 16 1 2`
>
> +packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
> +as hv2 ovs-appctl netdev-dummy/receive hv2-vif1 $packet
> +
> +echo "---------NB dump-----"
> +ovn-nbctl show
> +echo "---------------------"
> +ovn-nbctl list logical_router
> +echo "---------------------"
> +ovn-nbctl list logical_router_port
> +echo "---------------------"
> +
> +echo "---------SB dump-----"
> +ovn-sbctl list datapath_binding
> +echo "---------------------"
> +ovn-sbctl list port_binding
> +echo "---------------------"
> +ovn-sbctl dump-flows
> +
> +#echo "------ hv1 dump ----------"
> +#as hv1 ovs-ofctl dump-flows br-int
> +#echo "------ hv2 dump ----------"
> +#as hv2 ovs-ofctl dump-flows br-int
> +
> +# Packet to Expect at bob1
> +src_mac="000000010206"
> +dst_mac="f00000010205"
> +src_ip=`ip_to_hex 192 168 1 2`
> +dst_ip=`ip_to_hex 172 16 2 2`
>
> +expected=${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000
> +
> +$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv2/vif1-tx.pcap |
> trim_zeros > received.packets
> +echo $expected | trim_zeros > expout
> +AT_CHECK([cat received.packets], [0], [expout])
> +
> +# Packet to Expect at alice1
> +src_mac="000000010204"
> +dst_mac="f00000010204"
> +src_ip=`ip_to_hex 172 16 2 2`
> +dst_ip=`ip_to_hex 172 16 1 2`
>
> +expected=${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000
> +
> +$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv2/vif2-tx.pcap |
> trim_zeros > received1.packets
> +echo $expected | trim_zeros > expout
> +AT_CHECK([cat received1.packets], [0], [expout])
> +
> +for sim in hv1 hv2; do
> +    as $sim
> +    OVS_APP_EXIT_AND_WAIT([ovn-controller])
> +    OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])
> +    OVS_APP_EXIT_AND_WAIT([ovsdb-server])
> +done
> +
> +as ovn-sb
> +OVS_APP_EXIT_AND_WAIT([ovsdb-server])
> +
> +as ovn-nb
> +OVS_APP_EXIT_AND_WAIT([ovsdb-server])
> +
> +as northd
> +OVS_APP_EXIT_AND_WAIT([ovn-northd])
> +
> +as main
> +OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])
> +OVS_APP_EXIT_AND_WAIT([ovsdb-server])
> +
> +AT_CLEANUP
> --
> 1.9.1
>
> _______________________________________________
> dev mailing list
> [email protected]
> http://openvswitch.org/mailman/listinfo/dev
>
>
>
>
> _______________________________________________
> dev mailing list
> [email protected]
> http://openvswitch.org/mailman/listinfo/dev
>
_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev

Reply via email to