On Tue, May 10, 2016 at 11:02 AM, Guru Shetty <g...@ovn.org> wrote:

>
>
> On 9 May 2016 at 23:57, Mickey Spiegel <emspi...@us.ibm.com> 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.
>>
>

Exactly; in this network configuration, you would not use a local router to
connect Bob and alice since in the test only HV2 has R2 configured as local.
If you want Bob distributed and be able to reach Alice, then I would think
a distributed router is the clear choice.

Local router usage is optional and used to optimize flow processing and
download so that it does not happen where its needed and in the most simple
case, where both ingress and egress occur on the same chassis.




>
>> 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.
>>
>
Bob on HV1 would reach Alice on HV2 via switching.
So you end up with Bob on HV1 reaching Alice via switching decision only in
the overlay and Bob on HV2 reaching Alice including a routing decision.

I think that you really want to use a distributed router, in this case, by
definition.



>
>> 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 <dlu...@gmail.com> wrote: -----
>> To: Mickey Spiegel/San Jose/IBM@IBMUS
>> From: Darrell Ball <dlu...@gmail.com>
>> Date: 05/09/2016 09:11PM
>> Cc: d...@openvswitch.com
>> Subject: Re: [ovs-dev] [patch_v1] ovn: add local router support (RFC)
>>
>>
>>
>>
>> On Mon, May 9, 2016 at 4:40 PM, Mickey Spiegel <emspi...@us.ibm.com>
>> 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" <dev-boun...@openvswitch.org> wrote: -----
>> To: dlu...@gmail.com, d...@openvswitch.com
>> 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 <dlu...@gmail.com>
>> ---
>>  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
>> dev@openvswitch.org
>> http://openvswitch.org/mailman/listinfo/dev
>>
>>
>>
>>
>> _______________________________________________
>> dev mailing list
>> dev@openvswitch.org
>> http://openvswitch.org/mailman/listinfo/dev
>>
>
>
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to