[ovs-dev,v3] ofproto-dpif-xlate: makes OVS native tunneling honor tunnel-specified source addresses

Message ID 1523939352-26482-1-git-send-email-wenxu@ucloud.cn
State Superseded
Headers show
Series
  • [ovs-dev,v3] ofproto-dpif-xlate: makes OVS native tunneling honor tunnel-specified source addresses
Related show

Commit Message

wenxu April 17, 2018, 4:29 a.m.
From: wenxu <wenxu@ucloud.cn>

It makes OVS native tunneling honor tunnel-specified source addresses,
in the same way that Linux kernel tunneling honors them.

This patch made valid tun_src specified by flow-action can be used for
tunnel_src of packet. add a "local" property for a route entry and enhance
the priority of local route higher than user route.
Like the kernel space when lookup the route, if there are tun_src specified
by flow-action or port options. Check the tun_src wheather is a local
address, then lookup the route.

Signed-off-by: wenxu <wenxu@ucloud.cn>
Signed-off-by: frank.zeng <frank.zeng@ucloud.cn>
---
 lib/ovs-router.c             | 36 +++++++++++++++++++++++++++++-------
 lib/ovs-router.h             |  2 +-
 lib/route-table.c            |  8 +++++++-
 ofproto/ofproto-dpif-sflow.c |  2 +-
 ofproto/ofproto-dpif-xlate.c |  4 ++++
 5 files changed, 42 insertions(+), 10 deletions(-)

Comments

Ben Pfaff April 17, 2018, 3:45 p.m. | #1
On Tue, Apr 17, 2018 at 12:29:12PM +0800, wenxu@ucloud.cn wrote:
> From: wenxu <wenxu@ucloud.cn>
> 
> It makes OVS native tunneling honor tunnel-specified source addresses,
> in the same way that Linux kernel tunneling honors them.
> 
> This patch made valid tun_src specified by flow-action can be used for
> tunnel_src of packet. add a "local" property for a route entry and enhance
> the priority of local route higher than user route.
> Like the kernel space when lookup the route, if there are tun_src specified
> by flow-action or port options. Check the tun_src wheather is a local
> address, then lookup the route.
> 
> Signed-off-by: wenxu <wenxu@ucloud.cn>
> Signed-off-by: frank.zeng <frank.zeng@ucloud.cn>

Thanks a lot for this latest version.

This has patch conflicts due to a recent change in
ofproto/ofproto-dpif-sflow.c.  Would you mind rebasing?

This code tends to use booleans in correct, but somewhat nonidiomatic
ways.  For example:
            if (p_src->local != true) {
would more idiomatically be written as:
            if (!p_src->local) {

and:
        if (rt->priority == rt->plen || rt->local == true) {
as:
        if (rt->priority == rt->plen || rt->local) {

and:
        if (rtm->rtm_type == RTN_LOCAL) {
            change->rd.local = true;
        } else {
            change->rd.local = false;
        }
as:
        change->rd.local = rtm->rtm_type == RTN_LOCAL;

Would you mind adjusting the style?

I also noticed a doubled semicolon in sflow_choose_agent_address().

Thanks again,

Ben.

Patch

diff --git a/lib/ovs-router.c b/lib/ovs-router.c
index ad8bd62..f5cf59c 100644
--- a/lib/ovs-router.c
+++ b/lib/ovs-router.c
@@ -66,6 +66,7 @@  struct ovs_router_entry {
     struct in6_addr src_addr;
     uint8_t plen;
     uint8_t priority;
+    bool local;
     uint32_t mark;
 };
 
@@ -110,13 +111,28 @@  ovs_router_lookup(uint32_t mark, const struct in6_addr *ip6_dst,
     const struct cls_rule *cr;
     struct flow flow = {.ipv6_dst = *ip6_dst, .pkt_mark = mark};
 
+    if (src && ipv6_addr_is_set(src)) {
+        const struct cls_rule *cr_src;
+        struct flow flow_src = {.ipv6_dst = *src, .pkt_mark = mark};
+
+        cr_src = classifier_lookup(&cls, OVS_VERSION_MAX, &flow_src, NULL);
+        if (cr_src) {
+            struct ovs_router_entry *p_src = ovs_router_entry_cast(cr_src);
+            if (p_src->local != true) {
+                return false;
+            }
+        } else {
+            return false;
+        }
+    }
+
     cr = classifier_lookup(&cls, OVS_VERSION_MAX, &flow, NULL);
     if (cr) {
         struct ovs_router_entry *p = ovs_router_entry_cast(cr);
 
         ovs_strlcpy(output_bridge, p->output_bridge, IFNAMSIZ);
         *gw = p->gw;
-        if (src) {
+        if (src && !ipv6_addr_is_set(src)) {
             *src = p->src_addr;
         }
         return true;
@@ -197,7 +213,7 @@  out:
 }
 
 static int
-ovs_router_insert__(uint32_t mark, uint8_t priority,
+ovs_router_insert__(uint32_t mark, uint8_t priority, bool local,
                     const struct in6_addr *ip6_dst,
                     uint8_t plen, const char output_bridge[],
                     const struct in6_addr *gw)
@@ -217,6 +233,7 @@  ovs_router_insert__(uint32_t mark, uint8_t priority,
     p->mark = mark;
     p->nw_addr = match.flow.ipv6_dst;
     p->plen = plen;
+    p->local = local;
     p->priority = priority;
     err = get_src_addr(ip6_dst, output_bridge, &p->src_addr);
     if (err && ipv6_addr_is_set(gw)) {
@@ -249,10 +266,12 @@  ovs_router_insert__(uint32_t mark, uint8_t priority,
 
 void
 ovs_router_insert(uint32_t mark, const struct in6_addr *ip_dst, uint8_t plen,
-                  const char output_bridge[], const struct in6_addr *gw)
+                  bool local, const char output_bridge[], 
+                  const struct in6_addr *gw)
 {
     if (use_system_routing_table) {
-        ovs_router_insert__(mark, plen, ip_dst, plen, output_bridge, gw);
+        uint8_t priority = local ? plen + 64 : plen;
+        ovs_router_insert__(mark, priority, local, ip_dst, plen, output_bridge, gw);
     }
 }
 
@@ -360,7 +379,7 @@  ovs_router_add(struct unixctl_conn *conn, int argc,
         }
     }
 
-    err = ovs_router_insert__(mark, plen + 32, &ip6, plen, argv[2], &gw6);
+    err = ovs_router_insert__(mark, plen + 32, false, &ip6, plen, argv[2], &gw6);
     if (err) {
         unixctl_command_reply_error(conn, "Error while inserting route.");
     } else {
@@ -409,7 +428,7 @@  ovs_router_show(struct unixctl_conn *conn, int argc OVS_UNUSED,
     ds_put_format(&ds, "Route Table:\n");
     CLS_FOR_EACH(rt, cr, &cls) {
         uint8_t plen;
-        if (rt->priority == rt->plen) {
+        if (rt->priority == rt->plen || rt->local == true) {
             ds_put_format(&ds, "Cached: ");
         } else {
             ds_put_format(&ds, "User: ");
@@ -431,6 +450,9 @@  ovs_router_show(struct unixctl_conn *conn, int argc OVS_UNUSED,
         }
         ds_put_format(&ds, " SRC ");
         ipv6_format_mapped(&rt->src_addr, &ds);
+        if (rt->local) {
+            ds_put_format(&ds, " local");
+        }
         ds_put_format(&ds, "\n");
     }
     unixctl_command_reply(conn, ds_cstr(&ds));
@@ -441,7 +463,7 @@  static void
 ovs_router_lookup_cmd(struct unixctl_conn *conn, int argc,
                       const char *argv[], void *aux OVS_UNUSED)
 {
-    struct in6_addr gw, src;
+    struct in6_addr gw, src = in6addr_any;
     char iface[IFNAMSIZ];
     struct in6_addr ip6;
     unsigned int plen;
diff --git a/lib/ovs-router.h b/lib/ovs-router.h
index f65d652..34ea163 100644
--- a/lib/ovs-router.h
+++ b/lib/ovs-router.h
@@ -31,7 +31,7 @@  bool ovs_router_lookup(uint32_t mark, const struct in6_addr *ip_dst,
                        struct in6_addr *src, struct in6_addr *gw);
 void ovs_router_init(void);
 void ovs_router_insert(uint32_t mark, const struct in6_addr *ip_dst,
-                       uint8_t plen,
+                       uint8_t plen, bool local,
                        const char output_bridge[], const struct in6_addr *gw);
 void ovs_router_flush(void);
 
diff --git a/lib/route-table.c b/lib/route-table.c
index 2ee45e5..74afd66 100644
--- a/lib/route-table.c
+++ b/lib/route-table.c
@@ -47,6 +47,7 @@  VLOG_DEFINE_THIS_MODULE(route_table);
 struct route_data {
     /* Copied from struct rtmsg. */
     unsigned char rtm_dst_len;
+    bool local;
 
     /* Extracted from Netlink attributes. */
     struct in6_addr rta_dst; /* 0 if missing. */
@@ -245,6 +246,11 @@  route_table_parse(struct ofpbuf *buf, struct route_table_msg *change)
         }
         change->nlmsg_type     = nlmsg->nlmsg_type;
         change->rd.rtm_dst_len = rtm->rtm_dst_len + (ipv4 ? 96 : 0);
+        if (rtm->rtm_type == RTN_LOCAL) {
+            change->rd.local = true;
+        } else {
+            change->rd.local = false;
+        }
         if (attrs[RTA_OIF]) {
             rta_oif = nl_attr_get_u32(attrs[RTA_OIF]);
 
@@ -307,7 +313,7 @@  route_table_handle_msg(const struct route_table_msg *change)
         const struct route_data *rd = &change->rd;
 
         ovs_router_insert(rd->mark, &rd->rta_dst, rd->rtm_dst_len,
-                          rd->ifname, &rd->rta_gw);
+                          rd->local, rd->ifname, &rd->rta_gw);
     }
 }
 
diff --git a/ofproto/ofproto-dpif-sflow.c b/ofproto/ofproto-dpif-sflow.c
index 5d8c0e1..dbf2c02 100644
--- a/ofproto/ofproto-dpif-sflow.c
+++ b/ofproto/ofproto-dpif-sflow.c
@@ -468,7 +468,7 @@  sflow_choose_agent_address(const char *agent_device,
 
         if (inet_parse_active(target, SFL_DEFAULT_COLLECTOR_PORT, &sa.ss)
             && sa.ss.ss_family == AF_INET) {
-            struct in6_addr addr6, src, gw;
+            struct in6_addr addr6, gw, src = in6addr_any;;
 
             in6_addr_set_mapped_ipv4(&addr6, sa.sin.sin_addr.s_addr);
             /* sFlow only supports target in default routing table with
diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
index c8baba1..4f8ffbb 100644
--- a/ofproto/ofproto-dpif-xlate.c
+++ b/ofproto/ofproto-dpif-xlate.c
@@ -3320,6 +3320,10 @@  native_tunnel_output(struct xlate_ctx *ctx, const struct xport *xport,
     /* Backup flow & base_flow data. */
     memcpy(&old_base_flow, &ctx->base_flow, sizeof old_base_flow);
     memcpy(&old_flow, &ctx->xin->flow, sizeof old_flow);
+	
+    if (flow->tunnel.ip_src) {
+        in6_addr_set_mapped_ipv4(&s_ip6, flow->tunnel.ip_src);
+    }
 
     err = tnl_route_lookup_flow(ctx, flow, &d_ip6, &s_ip6, &out_dev);
     if (err) {