[ovs-dev] [PATCH 2/2] tunneling: add the GRE set_tunnel_nw_dst action

romain.lenglet at berabera.info romain.lenglet at berabera.info
Tue Oct 26 00:24:30 PDT 2010


From: Romain Lenglet <romain.lenglet at berabera.info>

This new action sets the destination IP address of the GRE packets for
a tunneled flow. If this action is not used, the address set for the
GRE port is used as a default value. This action must be used in
addition to an output action: first use set_tunnel_nw_dst to set the
destination address, then use output to output the flow into a GRE
vport. Header caching is automatically disabled for forwarding any
packet to which a set_tunnel_nw_dst action has been applied.
---
 ChangeLog                               |    1 +
 datapath/actions.c                      |    5 +++++
 datapath/datapath.c                     |    1 +
 datapath/datapath.h                     |    3 +++
 datapath/tunnel.c                       |   22 ++++++++++++++--------
 debian/changelog                        |    1 +
 include/openflow/nicira-ext.h           |   16 +++++++++++++++-
 include/openvswitch/datapath-protocol.h |   12 +++++++-----
 lib/odp-util.c                          |    4 ++++
 lib/ofp-parse.c                         |    6 ++++++
 lib/ofp-print.c                         |    8 ++++++++
 lib/ofp-util.c                          |    1 +
 ofproto/ofproto.c                       |    7 +++++++
 13 files changed, 73 insertions(+), 14 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 527957a..89a5ab0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,7 @@ v1.1.0pre2 - 13 Sep 2010
 ------------------------
     - Bug fixes
     - Add option to disable GRE remote IP address matching
+    - Add action to set the GRE destination IP address per flow
 
 v1.1.0pre1 - 31 Aug 2010
 ------------------------
diff --git a/datapath/actions.c b/datapath/actions.c
index 5904c83..20b88b2 100644
--- a/datapath/actions.c
+++ b/datapath/actions.c
@@ -438,6 +438,7 @@ int execute_actions(struct datapath *dp, struct sk_buff *skb,
 	}
 
 	OVS_CB(skb)->tun_id = 0;
+        OVS_CB(skb)->tun_nw_dst = 0;
 
 	for (; n_actions > 0; a++, n_actions--) {
 		if (prev_port != -1) {
@@ -462,6 +463,10 @@ int execute_actions(struct datapath *dp, struct sk_buff *skb,
 			OVS_CB(skb)->tun_id = a->tunnel.tun_id;
 			break;
 
+		case ODPAT_SET_TUNNEL_NW_DST:
+			OVS_CB(skb)->tun_nw_dst = a->nw_addr.nw_addr;
+			break;
+
 		case ODPAT_SET_DL_TCI:
 			skb = modify_vlan_tci(dp, skb, key, a, n_actions);
 			if (IS_ERR(skb))
diff --git a/datapath/datapath.c b/datapath/datapath.c
index 522d4ec..e46e5b5 100644
--- a/datapath/datapath.c
+++ b/datapath/datapath.c
@@ -891,6 +891,7 @@ static int validate_actions(const struct sw_flow_actions *actions)
 		case ODPAT_SET_TP_SRC:
 		case ODPAT_SET_TP_DST:
 		case ODPAT_SET_TUNNEL:
+		case ODPAT_SET_TUNNEL_NW_DST:
 		case ODPAT_SET_PRIORITY:
 		case ODPAT_POP_PRIORITY:
 		case ODPAT_DROP_SPOOFED_ARP:
diff --git a/datapath/datapath.h b/datapath/datapath.h
index 3a38235..804a203 100644
--- a/datapath/datapath.h
+++ b/datapath/datapath.h
@@ -140,12 +140,15 @@ enum csum_type {
  * kernel versions.
  * @tun_id: ID (in network byte order) of the tunnel that encapsulated this
  * packet. It is 0 if the packet was not received on a tunnel.
+ * @tun_nw_dst: The remote IP address (in network byte order) of the tunnel.
+ * It is 0 if no remote IP address is defined.
  */
 struct ovs_skb_cb {
 	struct dp_port		*dp_port;
 	struct sw_flow		*flow;
 	enum csum_type		ip_summed;
 	__be32			tun_id;
+        __be32                  tun_nw_dst;
 };
 #define OVS_CB(skb) ((struct ovs_skb_cb *)(skb)->cb)
 
diff --git a/datapath/tunnel.c b/datapath/tunnel.c
index 9c83a91..c6d0b1e 100644
--- a/datapath/tunnel.c
+++ b/datapath/tunnel.c
@@ -957,7 +957,8 @@ unlock:
 
 static struct rtable *find_route(struct vport *vport,
 				 const struct tnl_mutable_config *mutable,
-				 u8 tos, struct tnl_cache **cache)
+				 u8 tos, struct tnl_cache **cache,
+				 struct sk_buff *skb)
 {
 	struct tnl_vport *tnl_vport = tnl_vport_priv(vport);
 	struct tnl_cache *cur_cache = rcu_dereference(tnl_vport->cache);
@@ -965,17 +966,22 @@ static struct rtable *find_route(struct vport *vport,
 	*cache = NULL;
 	tos = RT_TOS(tos);
 
-	if (likely(tos == mutable->port_config.tos &&
+	if (!OVS_CB(skb)->tun_nw_dst &&
+	    likely(tos == mutable->port_config.tos &&
 		   check_cache_valid(cur_cache, mutable))) {
 		*cache = cur_cache;
 		return cur_cache->rt;
 	} else {
 		struct rtable *rt;
-		struct flowi fl = { .nl_u = { .ip4_u =
-					      { .daddr = mutable->port_config.daddr,
-						.saddr = mutable->port_config.saddr,
-						.tos = tos } },
-				    .proto = tnl_vport->tnl_ops->ipproto };
+		struct flowi fl = {
+			.nl_u = {
+				.ip4_u = {
+					.daddr = OVS_CB(skb)->tun_nw_dst ?
+						OVS_CB(skb)->tun_nw_dst :
+						mutable->port_config.daddr,
+					.saddr = mutable->port_config.saddr,
+					.tos = tos } },
+				.proto = tnl_vport->tnl_ops->ipproto };
 
 		if (unlikely(ip_route_output_key(&init_net, &rt, &fl)))
 			return NULL;
@@ -1197,7 +1203,7 @@ int tnl_send(struct vport *vport, struct sk_buff *skb)
 	tos = INET_ECN_encapsulate(tos, inner_tos);
 
 	/* Route lookup */
-	rt = find_route(vport, mutable, tos, &cache);
+	rt = find_route(vport, mutable, tos, &cache, skb);
 	if (unlikely(!rt))
 		goto error_free;
 	if (unlikely(!cache))
diff --git a/debian/changelog b/debian/changelog
index f427eb0..f36ff61 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -2,6 +2,7 @@ openvswitch (1.1.0pre2) unstable; urgency=low
 
   * Bug fixes
   * Add option to disable GRE remote IP address matching
+  * Add action to set the GRE destination IP address per flow
 
  -- Open vSwitch team <dev at openvswitch.org>  Mon, 13 Sep 2010 21:50:00 +0000
 
diff --git a/include/openflow/nicira-ext.h b/include/openflow/nicira-ext.h
index df2488b..f5a0142 100644
--- a/include/openflow/nicira-ext.h
+++ b/include/openflow/nicira-ext.h
@@ -152,7 +152,10 @@ enum nx_action_subtype {
 
     /* Restore the queue to the value it was before any NXAST_SET_QUEUE
      * actions were used. */
-    NXAST_POP_QUEUE
+    NXAST_POP_QUEUE,
+
+    /* Set encapsulating tunnel remote IP address. */
+    NXAST_SET_TUNNEL_NW_DST
 };
 
 /* Action structure for NXAST_RESUBMIT. */
@@ -177,6 +180,17 @@ struct nx_action_set_tunnel {
 };
 OFP_ASSERT(sizeof(struct nx_action_set_tunnel) == 16);
 
+/* Action structure for NXAST_SET_TUNNEL_NW_DST. */
+struct nx_action_set_tunnel_nw_dst {
+    uint16_t type;                  /* OFPAT_VENDOR. */
+    uint16_t len;                   /* Length is 16. */
+    uint32_t vendor;                /* NX_VENDOR_ID. */
+    uint16_t subtype;               /* NXAST_SET_TUNNEL_NW_DST. */
+    uint8_t pad[2];
+    uint32_t nw_addr;                /* Tunnel remote IP address. */
+};
+OFP_ASSERT(sizeof(struct nx_action_set_tunnel_nw_dst) == 16);
+
 /* Action structure for NXAST_SET_QUEUE. */
 struct nx_action_set_queue {
     uint16_t type;                  /* OFPAT_VENDOR. */
diff --git a/include/openvswitch/datapath-protocol.h b/include/openvswitch/datapath-protocol.h
index b0e9dfb..ac3450b 100644
--- a/include/openvswitch/datapath-protocol.h
+++ b/include/openvswitch/datapath-protocol.h
@@ -268,10 +268,11 @@ struct odp_flowvec {
 #define ODPAT_SET_TP_SRC        11   /* TCP/UDP source port. */
 #define ODPAT_SET_TP_DST        12   /* TCP/UDP destination port. */
 #define ODPAT_SET_TUNNEL        13   /* Set the encapsulating tunnel ID. */
-#define ODPAT_SET_PRIORITY      14   /* Set skb->priority. */
-#define ODPAT_POP_PRIORITY      15   /* Restore original skb->priority. */
-#define ODPAT_DROP_SPOOFED_ARP  16   /* Drop ARPs with spoofed source MAC. */
-#define ODPAT_N_ACTIONS         17
+#define ODPAT_SET_TUNNEL_NW_DST 14   /* Set the tunnel remote IP address. */
+#define ODPAT_SET_PRIORITY      15   /* Set skb->priority. */
+#define ODPAT_POP_PRIORITY      16   /* Restore original skb->priority. */
+#define ODPAT_DROP_SPOOFED_ARP  17   /* Drop ARPs with spoofed source MAC. */
+#define ODPAT_N_ACTIONS         18
 
 struct odp_action_output {
     uint16_t type;              /* ODPAT_OUTPUT. */
@@ -305,7 +306,8 @@ struct odp_action_dl_addr {
     uint8_t dl_addr[6];         /* Ethernet address. */
 };
 
-/* Action structure for ODPAT_SET_NW_SRC/DST. */
+/* Action structure for ODPAT_SET_NW_SRC/DST and
+   ODPAT_SET_TUNNEL_NW_DST. */
 struct odp_action_nw_addr {
     uint16_t type;              /* ODPAT_SET_TW_SRC/DST. */
     uint16_t reserved;
diff --git a/lib/odp-util.c b/lib/odp-util.c
index 511ec3a..9b297d9 100644
--- a/lib/odp-util.c
+++ b/lib/odp-util.c
@@ -71,6 +71,10 @@ format_odp_action(struct ds *ds, const union odp_action *a)
     case ODPAT_SET_TUNNEL:
         ds_put_format(ds, "set_tunnel(0x%08"PRIx32")", ntohl(a->tunnel.tun_id));
         break;
+    case ODPAT_SET_TUNNEL_NW_DST:
+        ds_put_format(ds, "set_tunnel_nw_dst("IP_FMT")",
+                      IP_ARGS(&a->nw_addr.nw_addr));
+        break;
     case ODPAT_SET_DL_TCI:
         ds_put_format(ds, "set_tci(vid=%"PRIu16",pcp=%d)",
                       vlan_tci_to_vid(a->dl_tci.tci),
diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c
index e6af036..192f80f 100644
--- a/lib/ofp-parse.c
+++ b/lib/ofp-parse.c
@@ -266,6 +266,12 @@ str_to_action(char *str, struct ofpbuf *b)
             nast->vendor = htonl(NX_VENDOR_ID);
             nast->subtype = htons(NXAST_SET_TUNNEL);
             nast->tun_id = htonl(str_to_u32(arg));
+        } else if (!strcasecmp(act, "set_tunnel_nw_dst")) {
+            struct nx_action_set_tunnel_nw_dst *nastnd;
+            nastnd = put_action(b, sizeof *nastnd, OFPAT_VENDOR);
+            nastnd->vendor = htonl(NX_VENDOR_ID);
+            nastnd->subtype = htons(NXAST_SET_TUNNEL_NW_DST);
+            str_to_ip(arg, &nastnd->nw_addr);
         } else if (!strcasecmp(act, "drop_spoofed_arp")) {
             struct nx_action_header *nah;
             nah = put_action(b, sizeof *nah, OFPAT_VENDOR);
diff --git a/lib/ofp-print.c b/lib/ofp-print.c
index 2591484..074d979 100644
--- a/lib/ofp-print.c
+++ b/lib/ofp-print.c
@@ -201,6 +201,14 @@ ofp_print_nx_action(struct ds *string, const struct nx_action_header *nah)
         break;
     }
 
+    case NXAST_SET_TUNNEL_NW_DST: {
+        const struct nx_action_set_tunnel_nw_dst *nastnd =
+            (struct nx_action_set_tunnel_nw_dst *)nah;
+        ds_put_format(string, "set_tunnel_nw_dst:"IP_FMT,
+                      IP_ARGS(&nastnd->nw_addr));
+        break;
+    }
+
     case NXAST_DROP_SPOOFED_ARP:
         ds_put_cstr(string, "drop_spoofed_arp");
         break;
diff --git a/lib/ofp-util.c b/lib/ofp-util.c
index 99e5943..cf95b47 100644
--- a/lib/ofp-util.c
+++ b/lib/ofp-util.c
@@ -564,6 +564,7 @@ check_nicira_action(const union ofp_action *a, unsigned int len)
     switch (ntohs(nah->subtype)) {
     case NXAST_RESUBMIT:
     case NXAST_SET_TUNNEL:
+    case NXAST_SET_TUNNEL_NW_DST:
     case NXAST_DROP_SPOOFED_ARP:
     case NXAST_SET_QUEUE:
     case NXAST_POP_QUEUE:
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index ab5d476..1e2cc61 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -2700,6 +2700,7 @@ xlate_nicira_action(struct action_xlate_ctx *ctx,
 {
     const struct nx_action_resubmit *nar;
     const struct nx_action_set_tunnel *nast;
+    const struct nx_action_set_tunnel_nw_dst *nastnd;
     const struct nx_action_set_queue *nasq;
     union odp_action *oa;
     int subtype = ntohs(nah->subtype);
@@ -2717,6 +2718,12 @@ xlate_nicira_action(struct action_xlate_ctx *ctx,
         ctx->flow.tun_id = oa->tunnel.tun_id = nast->tun_id;
         break;
 
+    case NXAST_SET_TUNNEL_NW_DST:
+        nastnd = (const struct nx_action_set_tunnel_nw_dst *) nah;
+        oa = odp_actions_add(ctx->out, ODPAT_SET_TUNNEL_NW_DST);
+        oa->nw_addr.nw_addr = nastnd->nw_addr;
+        break;
+
     case NXAST_DROP_SPOOFED_ARP:
         if (ctx->flow.dl_type == htons(ETH_TYPE_ARP)) {
             odp_actions_add(ctx->out, ODPAT_DROP_SPOOFED_ARP);
-- 
1.7.2.3





More information about the dev mailing list