[ovs-dev] [PATCH 7/8] nsh: support for setting nsh contexts

pritesh pritesh.kothari at cisco.com
Fri Sep 20 08:04:24 UTC 2013


Support for setting the nsh network and service contexts is added here.
The support is added only for adding context while the port is created.
Support for carrying forward context from incoming packet to the
outgoing packet is not supported yet.

Signed-off-by: pritesh <pritesh.kothari at cisco.com>

diff --git a/datapath/linux/compat/include/net/vxlan.h b/datapath/linux/compat/include/net/vxlan.h
index 1c15dfb..34ec724 100644
--- a/datapath/linux/compat/include/net/vxlan.h
+++ b/datapath/linux/compat/include/net/vxlan.h
@@ -27,7 +27,7 @@ struct vxlan_sock *vxlan_sock_add(struct net *net, __be16 port,
 void vxlan_sock_release(struct vxlan_sock *vs);
 
 int vxlan_xmit_skb(struct vxlan_sock *vs,
-		   struct rtable *rt, struct sk_buff *skb,
+		   struct rtable *rt, struct sk_buff *skb, struct nsh_ctx *nc,
 		   __be32 src, __be32 dst, __u8 tos, __u8 ttl, __be16 df,
 		   __be16 src_port, __be16 dst_port, __be32 vni, __be32 nsp);
 
diff --git a/datapath/linux/compat/vxlan.c b/datapath/linux/compat/vxlan.c
index 8a6d864..5d21068 100644
--- a/datapath/linux/compat/vxlan.c
+++ b/datapath/linux/compat/vxlan.c
@@ -246,7 +246,7 @@ static int handle_offloads(struct sk_buff *skb)
 }
 
 int vxlan_xmit_skb(struct vxlan_sock *vs,
-		   struct rtable *rt, struct sk_buff *skb,
+		   struct rtable *rt, struct sk_buff *skb, struct nsh_ctx *nc,
 		   __be32 src, __be32 dst, __u8 tos, __u8 ttl, __be16 df,
 		   __be16 src_port, __be16 dst_port, __be32 vni, __be32 nsp)
 {
@@ -286,8 +286,8 @@ int vxlan_xmit_skb(struct vxlan_sock *vs,
 		nsh->b.svc_idx = nsi ? nsi : 0x01;
 		nsh->b.proto = htons(NSH_P_TEB);
 		nsh->b.svc_path = nsp & htonl(NSH_M_NSP);
-		nsh->b.c = 0;
-		memset(&nsh->c, 0x00, sizeof nsh->c);
+		nsh->b.c = (nc->npc || nc->nsc || nc->spc || nc->ssc) ? 1 : 0;
+		memcpy(&nsh->c, nc, sizeof nsh->c);
 	}
 
 	vxh = (struct vxlanhdr *) __skb_push(skb, sizeof(*vxh));
diff --git a/datapath/vport-vxlan.c b/datapath/vport-vxlan.c
index b24c235..d11d5fa 100644
--- a/datapath/vport-vxlan.c
+++ b/datapath/vport-vxlan.c
@@ -50,6 +50,7 @@
  */
 struct vxlan_port {
 	struct vxlan_sock *vs;
+	struct nsh_ctx nsh_ctx;
 	char name[IFNAMSIZ];
 };
 
@@ -80,9 +81,23 @@ static int vxlan_get_options(const struct vport *vport, struct sk_buff *skb)
 {
 	struct vxlan_port *vxlan_port = vxlan_vport(vport);
 	__be16 dst_port = inet_sport(vxlan_port->vs->sock->sk);
+	struct nsh_ctx *n = &vxlan_port->nsh_ctx;
 
 	if (nla_put_u16(skb, OVS_TUNNEL_ATTR_DST_PORT, ntohs(dst_port)))
 		return -EMSGSIZE;
+
+	if (nla_put_u32(skb, OVS_TUNNEL_ATTR_NSH_NPC, ntohl(n->npc)))
+		return -EMSGSIZE;
+
+	if (nla_put_u32(skb, OVS_TUNNEL_ATTR_NSH_NSC, ntohl(n->nsc)))
+		return -EMSGSIZE;
+
+	if (nla_put_u32(skb, OVS_TUNNEL_ATTR_NSH_SPC, ntohl(n->spc)))
+		return -EMSGSIZE;
+
+	if (nla_put_u32(skb, OVS_TUNNEL_ATTR_NSH_SSC, ntohl(n->ssc)))
+		return -EMSGSIZE;
+
 	return 0;
 }
 
@@ -134,6 +149,28 @@ static struct vport *vxlan_tnl_create(const struct vport_parms *parms)
 	}
 	vxlan_port->vs = vs;
 
+	memset(&vxlan_port->nsh_ctx, 0x00, sizeof(vxlan_port->nsh_ctx));
+
+	a = nla_find_nested(options, OVS_TUNNEL_ATTR_NSH_NPC);
+	if (a && nla_len(a) == sizeof(u32)) {
+		vxlan_port->nsh_ctx.npc = htonl(nla_get_u32(a));
+	}
+
+	a = nla_find_nested(options, OVS_TUNNEL_ATTR_NSH_NSC);
+	if (a && nla_len(a) == sizeof(u32)) {
+		vxlan_port->nsh_ctx.nsc = htonl(nla_get_u32(a));
+	}
+
+	a = nla_find_nested(options, OVS_TUNNEL_ATTR_NSH_SPC);
+	if (a && nla_len(a) == sizeof(u32)) {
+		vxlan_port->nsh_ctx.spc = htonl(nla_get_u32(a));
+	}
+
+	a = nla_find_nested(options, OVS_TUNNEL_ATTR_NSH_SSC);
+	if (a && nla_len(a) == sizeof(u32)) {
+		vxlan_port->nsh_ctx.ssc = htonl(nla_get_u32(a));
+	}
+
 	return vport;
 
 error:
@@ -178,7 +215,7 @@ static int vxlan_tnl_send(struct vport *vport, struct sk_buff *skb)
 	inet_get_local_port_range(&port_min, &port_max);
 	src_port = vxlan_src_port(port_min, port_max, skb);
 
-	err = vxlan_xmit_skb(vxlan_port->vs, rt, skb,
+	err = vxlan_xmit_skb(vxlan_port->vs, rt, skb, &vxlan_port->nsh_ctx,
 			     saddr, OVS_CB(skb)->tun_key->ipv4_dst,
 			     OVS_CB(skb)->tun_key->ipv4_tos,
 			     OVS_CB(skb)->tun_key->ipv4_ttl, df,
diff --git a/include/linux/openvswitch.h b/include/linux/openvswitch.h
index de9e9e4..15dfdf1 100644
--- a/include/linux/openvswitch.h
+++ b/include/linux/openvswitch.h
@@ -240,6 +240,10 @@ enum ovs_vport_attr {
 enum {
 	OVS_TUNNEL_ATTR_UNSPEC,
 	OVS_TUNNEL_ATTR_DST_PORT, /* 16-bit UDP port, used by L4 tunnels. */
+	OVS_TUNNEL_ATTR_NSH_NPC,  /* 32-bit NSH network platform context */
+	OVS_TUNNEL_ATTR_NSH_NSC,  /* 32-bit NSH network shared context */
+	OVS_TUNNEL_ATTR_NSH_SPC,  /* 32-bit NSH service platform context */
+	OVS_TUNNEL_ATTR_NSH_SSC,  /* 32-bit NSH service shared context */
 	__OVS_TUNNEL_ATTR_MAX
 };
 
diff --git a/lib/dpif-linux.c b/lib/dpif-linux.c
index 6f75f57..4dbebc4 100644
--- a/lib/dpif-linux.c
+++ b/lib/dpif-linux.c
@@ -515,10 +515,27 @@ dpif_linux_port_add__(struct dpif *dpif_, struct netdev *netdev,
     }
 
     tnl_cfg = netdev_get_tunnel_config(netdev);
-    if (tnl_cfg && tnl_cfg->dst_port != 0) {
+    if (tnl_cfg) {
         ofpbuf_use_stack(&options, options_stub, sizeof options_stub);
-        nl_msg_put_u16(&options, OVS_TUNNEL_ATTR_DST_PORT,
-                       ntohs(tnl_cfg->dst_port));
+
+        if (tnl_cfg->dst_port != 0) {
+            nl_msg_put_u16(&options, OVS_TUNNEL_ATTR_DST_PORT,
+                           ntohs(tnl_cfg->dst_port));
+        }
+
+        /* doesn't matter if nsh ctx params are zero, send them anyways */
+        nl_msg_put_u32(&options, OVS_TUNNEL_ATTR_NSH_NPC,
+                       ntohl(tnl_cfg->nsh_npc));
+
+        nl_msg_put_u32(&options, OVS_TUNNEL_ATTR_NSH_NSC,
+                       ntohl(tnl_cfg->nsh_nsc));
+
+        nl_msg_put_u32(&options, OVS_TUNNEL_ATTR_NSH_SPC,
+                       ntohl(tnl_cfg->nsh_spc));
+
+        nl_msg_put_u32(&options, OVS_TUNNEL_ATTR_NSH_SSC,
+                       ntohl(tnl_cfg->nsh_ssc));
+
         request.options = options.data;
         request.options_len = options.size;
     }
diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c
index 4a2ca52..7388b8c 100644
--- a/lib/netdev-vport.c
+++ b/lib/netdev-vport.c
@@ -120,6 +120,17 @@ netdev_vport_needs_dst_port(const struct netdev *dev)
             (!strcmp("vxlan", type) || !strcmp("lisp", type)));
 }
 
+static bool
+netdev_vport_is_nsh(const struct netdev *dev)
+{
+    const struct netdev_class *class = netdev_get_class(dev);
+    const char *type = netdev_get_type(dev);
+
+    return (class->get_config == get_tunnel_config &&
+            (!strcmp("vxlan", type) || !strcmp("lisp", type) ||
+             !strcmp("gre", type) || !strcmp("gre64", type)));
+}
+
 const char *
 netdev_vport_class_get_dpif_port(const struct netdev_class *class)
 {
@@ -387,12 +398,14 @@ set_tunnel_config(struct netdev *dev_, const struct smap *args)
     bool ipsec_mech_set, needs_dst_port, has_csum;
     struct netdev_tunnel_config tnl_cfg;
     struct smap_node *node;
+    bool is_nsh;
 
     has_csum = strstr(type, "gre");
     ipsec_mech_set = false;
     memset(&tnl_cfg, 0, sizeof tnl_cfg);
 
     needs_dst_port = netdev_vport_needs_dst_port(dev_);
+    is_nsh = netdev_vport_is_nsh(dev_);
     tnl_cfg.ipsec = strstr(type, "ipsec");
     tnl_cfg.dont_fragment = true;
 
@@ -450,6 +463,14 @@ set_tunnel_config(struct netdev *dev_, const struct smap *args)
             if (!strcmp(node->value, "false")) {
                 tnl_cfg.dont_fragment = false;
             }
+        } else if (!strcmp(node->key, "nsh_npc") && is_nsh) {
+            tnl_cfg.nsh_npc = htonl(atol(node->value));
+        } else if (!strcmp(node->key, "nsh_nsc") && is_nsh) {
+            tnl_cfg.nsh_nsc = htonl(atol(node->value));
+        } else if (!strcmp(node->key, "nsh_spc") && is_nsh) {
+            tnl_cfg.nsh_spc = htonl(atol(node->value));
+        } else if (!strcmp(node->key, "nsh_ssc") && is_nsh) {
+            tnl_cfg.nsh_ssc = htonl(atol(node->value));
         } else if (!strcmp(node->key, "peer_cert") && tnl_cfg.ipsec) {
             if (smap_get(args, "certificate")) {
                 ipsec_mech_set = true;
@@ -597,6 +618,7 @@ get_tunnel_config(const struct netdev *dev, struct smap *args)
     struct netdev_vport *netdev = netdev_vport_cast(dev);
     struct netdev_tunnel_config tnl_cfg;
     const char *type = netdev_get_type(dev);
+    bool is_nsh = netdev_vport_is_nsh(dev);
 
     ovs_mutex_lock(&netdev->mutex);
     tnl_cfg = netdev->tnl_cfg;
@@ -656,6 +678,25 @@ get_tunnel_config(const struct netdev *dev, struct smap *args)
         }
     }
 
+    if (tnl_cfg.in_nsi_flow && tnl_cfg.out_nsi_flow) {
+        smap_add(args, "nsi", "flow");
+    } else if (tnl_cfg.in_nsi_present && tnl_cfg.out_nsi_present
+               && tnl_cfg.in_nsi == tnl_cfg.out_nsi) {
+        smap_add_format(args, "nsi", "%"PRIu8, tnl_cfg.in_nsi);
+    } else {
+        if (tnl_cfg.in_nsi_flow) {
+            smap_add(args, "in_nsi", "flow");
+        } else if (tnl_cfg.in_nsi_present) {
+            smap_add_format(args, "in_nsi", "%"PRIu8, tnl_cfg.in_nsi);
+        }
+
+        if (tnl_cfg.out_nsi_flow) {
+            smap_add(args, "out_nsi", "flow");
+        } else if (tnl_cfg.out_nsi_present) {
+            smap_add_format(args, "out_nsi", "%"PRIu8, tnl_cfg.out_nsi);
+        }
+    }
+
     if (tnl_cfg.ttl_inherit) {
         smap_add(args, "ttl", "inherit");
     } else if (tnl_cfg.ttl != DEFAULT_TTL) {
@@ -685,6 +726,22 @@ get_tunnel_config(const struct netdev *dev, struct smap *args)
         smap_add(args, "df_default", "false");
     }
 
+    if (is_nsh && tnl_cfg.nsh_npc) {
+        smap_add_format(args, "nsh_npc", "%d", ntohl(tnl_cfg.nsh_npc));
+    }
+
+    if (is_nsh && tnl_cfg.nsh_nsc) {
+        smap_add_format(args, "nsh_nsc", "%d", ntohl(tnl_cfg.nsh_nsc));
+    }
+
+    if (is_nsh && tnl_cfg.nsh_spc) {
+        smap_add_format(args, "nsh_spc", "%d", ntohl(tnl_cfg.nsh_spc));
+    }
+
+    if (is_nsh && tnl_cfg.nsh_ssc) {
+        smap_add_format(args, "nsh_ssc", "%d", ntohl(tnl_cfg.nsh_ssc));
+    }
+
     return 0;
 }
 
diff --git a/lib/netdev.h b/lib/netdev.h
index c23fe25..0b69841 100644
--- a/lib/netdev.h
+++ b/lib/netdev.h
@@ -142,6 +142,11 @@ struct netdev_tunnel_config {
     bool csum;
     bool ipsec;
     bool dont_fragment;
+
+    ovs_be32 nsh_npc;           /* NSH network platform context */
+    ovs_be32 nsh_nsc;           /* NSH network shared context */
+    ovs_be32 nsh_spc;           /* NSH service platform context */
+    ovs_be32 nsh_ssc;           /* NSH service shared context */
 };
 
 void netdev_run(void);
-- 
1.7.9.5




More information about the dev mailing list