aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/uapi/linux/openvswitch.h2
-rw-r--r--net/openvswitch/actions.c5
-rw-r--r--net/openvswitch/datapath.h2
-rw-r--r--net/openvswitch/flow.c6
-rw-r--r--net/openvswitch/flow.h30
-rw-r--r--net/openvswitch/flow_netlink.c38
-rw-r--r--net/openvswitch/vport-gre.c16
-rw-r--r--net/openvswitch/vport-vxlan.c10
-rw-r--r--net/openvswitch/vport.c6
-rw-r--r--net/openvswitch/vport.h2
10 files changed, 74 insertions, 43 deletions
diff --git a/include/uapi/linux/openvswitch.h b/include/uapi/linux/openvswitch.h
index 7c06106f5af5..6753032832e2 100644
--- a/include/uapi/linux/openvswitch.h
+++ b/include/uapi/linux/openvswitch.h
@@ -294,7 +294,7 @@ enum ovs_key_attr {
294 OVS_KEY_ATTR_RECIRC_ID, /* u32 recirc id */ 294 OVS_KEY_ATTR_RECIRC_ID, /* u32 recirc id */
295 295
296#ifdef __KERNEL__ 296#ifdef __KERNEL__
297 OVS_KEY_ATTR_IPV4_TUNNEL, /* struct ovs_key_ipv4_tunnel */ 297 OVS_KEY_ATTR_TUNNEL_INFO, /* struct ovs_tunnel_info */
298#endif 298#endif
299 __OVS_KEY_ATTR_MAX 299 __OVS_KEY_ATTR_MAX
300}; 300};
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index 6932a42e41a2..006886dbee36 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -590,8 +590,8 @@ static int execute_set_action(struct sk_buff *skb,
590 skb->mark = nla_get_u32(nested_attr); 590 skb->mark = nla_get_u32(nested_attr);
591 break; 591 break;
592 592
593 case OVS_KEY_ATTR_IPV4_TUNNEL: 593 case OVS_KEY_ATTR_TUNNEL_INFO:
594 OVS_CB(skb)->egress_tun_key = nla_data(nested_attr); 594 OVS_CB(skb)->egress_tun_info = nla_data(nested_attr);
595 break; 595 break;
596 596
597 case OVS_KEY_ATTR_ETHERNET: 597 case OVS_KEY_ATTR_ETHERNET:
@@ -778,6 +778,7 @@ int ovs_execute_actions(struct datapath *dp, struct sk_buff *skb,
778 acts = rcu_dereference(OVS_CB(skb)->flow->sf_acts); 778 acts = rcu_dereference(OVS_CB(skb)->flow->sf_acts);
779 779
780 this_cpu_inc(exec_actions_level); 780 this_cpu_inc(exec_actions_level);
781 OVS_CB(skb)->egress_tun_info = NULL;
781 err = do_execute_actions(dp, skb, key, 782 err = do_execute_actions(dp, skb, key,
782 acts->actions, acts->actions_len); 783 acts->actions, acts->actions_len);
783 784
diff --git a/net/openvswitch/datapath.h b/net/openvswitch/datapath.h
index ac3f3df96961..974135439c5c 100644
--- a/net/openvswitch/datapath.h
+++ b/net/openvswitch/datapath.h
@@ -102,8 +102,8 @@ struct datapath {
102 */ 102 */
103struct ovs_skb_cb { 103struct ovs_skb_cb {
104 struct sw_flow *flow; 104 struct sw_flow *flow;
105 struct ovs_tunnel_info *egress_tun_info;
105 struct vport *input_vport; 106 struct vport *input_vport;
106 struct ovs_key_ipv4_tunnel *egress_tun_key;
107}; 107};
108#define OVS_CB(skb) ((struct ovs_skb_cb *)(skb)->cb) 108#define OVS_CB(skb) ((struct ovs_skb_cb *)(skb)->cb)
109 109
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index 913bdc1a83c0..2924cb340868 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -642,12 +642,12 @@ int ovs_flow_key_update(struct sk_buff *skb, struct sw_flow_key *key)
642 return key_extract(skb, key); 642 return key_extract(skb, key);
643} 643}
644 644
645int ovs_flow_key_extract(struct ovs_key_ipv4_tunnel *tun_key, 645int ovs_flow_key_extract(struct ovs_tunnel_info *tun_info,
646 struct sk_buff *skb, struct sw_flow_key *key) 646 struct sk_buff *skb, struct sw_flow_key *key)
647{ 647{
648 /* Extract metadata from packet. */ 648 /* Extract metadata from packet. */
649 if (tun_key) 649 if (tun_info)
650 memcpy(&key->tun_key, tun_key, sizeof(key->tun_key)); 650 memcpy(&key->tun_key, &tun_info->tunnel, sizeof(key->tun_key));
651 else 651 else
652 memset(&key->tun_key, 0, sizeof(key->tun_key)); 652 memset(&key->tun_key, 0, sizeof(key->tun_key));
653 653
diff --git a/net/openvswitch/flow.h b/net/openvswitch/flow.h
index 0f5db4ec565d..fe5a71b81c1f 100644
--- a/net/openvswitch/flow.h
+++ b/net/openvswitch/flow.h
@@ -49,20 +49,24 @@ struct ovs_key_ipv4_tunnel {
49 u8 ipv4_ttl; 49 u8 ipv4_ttl;
50} __packed __aligned(4); /* Minimize padding. */ 50} __packed __aligned(4); /* Minimize padding. */
51 51
52static inline void ovs_flow_tun_key_init(struct ovs_key_ipv4_tunnel *tun_key, 52struct ovs_tunnel_info {
53 const struct iphdr *iph, __be64 tun_id, 53 struct ovs_key_ipv4_tunnel tunnel;
54 __be16 tun_flags) 54};
55
56static inline void ovs_flow_tun_info_init(struct ovs_tunnel_info *tun_info,
57 const struct iphdr *iph,
58 __be64 tun_id, __be16 tun_flags)
55{ 59{
56 tun_key->tun_id = tun_id; 60 tun_info->tunnel.tun_id = tun_id;
57 tun_key->ipv4_src = iph->saddr; 61 tun_info->tunnel.ipv4_src = iph->saddr;
58 tun_key->ipv4_dst = iph->daddr; 62 tun_info->tunnel.ipv4_dst = iph->daddr;
59 tun_key->ipv4_tos = iph->tos; 63 tun_info->tunnel.ipv4_tos = iph->tos;
60 tun_key->ipv4_ttl = iph->ttl; 64 tun_info->tunnel.ipv4_ttl = iph->ttl;
61 tun_key->tun_flags = tun_flags; 65 tun_info->tunnel.tun_flags = tun_flags;
62 66
63 /* clear struct padding. */ 67 /* clear struct padding. */
64 memset((unsigned char *) tun_key + OVS_TUNNEL_KEY_SIZE, 0, 68 memset((unsigned char *)&tun_info->tunnel + OVS_TUNNEL_KEY_SIZE, 0,
65 sizeof(*tun_key) - OVS_TUNNEL_KEY_SIZE); 69 sizeof(tun_info->tunnel) - OVS_TUNNEL_KEY_SIZE);
66} 70}
67 71
68struct sw_flow_key { 72struct sw_flow_key {
@@ -190,8 +194,8 @@ void ovs_flow_stats_clear(struct sw_flow *);
190u64 ovs_flow_used_time(unsigned long flow_jiffies); 194u64 ovs_flow_used_time(unsigned long flow_jiffies);
191 195
192int ovs_flow_key_update(struct sk_buff *skb, struct sw_flow_key *key); 196int ovs_flow_key_update(struct sk_buff *skb, struct sw_flow_key *key);
193int ovs_flow_key_extract(struct ovs_key_ipv4_tunnel *tun_key, 197int ovs_flow_key_extract(struct ovs_tunnel_info *tun_info, struct sk_buff *skb,
194 struct sk_buff *skb, struct sw_flow_key *key); 198 struct sw_flow_key *key);
195/* Extract key from packet coming from userspace. */ 199/* Extract key from packet coming from userspace. */
196int ovs_flow_key_extract_userspace(const struct nlattr *attr, 200int ovs_flow_key_extract_userspace(const struct nlattr *attr,
197 struct sk_buff *skb, 201 struct sk_buff *skb,
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
index 22c855fa0bc2..5d6194d9dadc 100644
--- a/net/openvswitch/flow_netlink.c
+++ b/net/openvswitch/flow_netlink.c
@@ -1148,13 +1148,14 @@ out:
1148 return (struct nlattr *) ((unsigned char *)(*sfa) + next_offset); 1148 return (struct nlattr *) ((unsigned char *)(*sfa) + next_offset);
1149} 1149}
1150 1150
1151static int add_action(struct sw_flow_actions **sfa, int attrtype, void *data, int len) 1151static struct nlattr *__add_action(struct sw_flow_actions **sfa,
1152 int attrtype, void *data, int len)
1152{ 1153{
1153 struct nlattr *a; 1154 struct nlattr *a;
1154 1155
1155 a = reserve_sfa_size(sfa, nla_attr_size(len)); 1156 a = reserve_sfa_size(sfa, nla_attr_size(len));
1156 if (IS_ERR(a)) 1157 if (IS_ERR(a))
1157 return PTR_ERR(a); 1158 return a;
1158 1159
1159 a->nla_type = attrtype; 1160 a->nla_type = attrtype;
1160 a->nla_len = nla_attr_size(len); 1161 a->nla_len = nla_attr_size(len);
@@ -1163,6 +1164,18 @@ static int add_action(struct sw_flow_actions **sfa, int attrtype, void *data, in
1163 memcpy(nla_data(a), data, len); 1164 memcpy(nla_data(a), data, len);
1164 memset((unsigned char *) a + a->nla_len, 0, nla_padlen(len)); 1165 memset((unsigned char *) a + a->nla_len, 0, nla_padlen(len));
1165 1166
1167 return a;
1168}
1169
1170static int add_action(struct sw_flow_actions **sfa, int attrtype,
1171 void *data, int len)
1172{
1173 struct nlattr *a;
1174
1175 a = __add_action(sfa, attrtype, data, len);
1176 if (IS_ERR(a))
1177 return PTR_ERR(a);
1178
1166 return 0; 1179 return 0;
1167} 1180}
1168 1181
@@ -1268,6 +1281,8 @@ static int validate_and_copy_set_tun(const struct nlattr *attr,
1268{ 1281{
1269 struct sw_flow_match match; 1282 struct sw_flow_match match;
1270 struct sw_flow_key key; 1283 struct sw_flow_key key;
1284 struct ovs_tunnel_info *tun_info;
1285 struct nlattr *a;
1271 int err, start; 1286 int err, start;
1272 1287
1273 ovs_match_init(&match, &key, NULL); 1288 ovs_match_init(&match, &key, NULL);
@@ -1279,8 +1294,14 @@ static int validate_and_copy_set_tun(const struct nlattr *attr,
1279 if (start < 0) 1294 if (start < 0)
1280 return start; 1295 return start;
1281 1296
1282 err = add_action(sfa, OVS_KEY_ATTR_IPV4_TUNNEL, &match.key->tun_key, 1297 a = __add_action(sfa, OVS_KEY_ATTR_TUNNEL_INFO, NULL,
1283 sizeof(match.key->tun_key)); 1298 sizeof(*tun_info));
1299 if (IS_ERR(a))
1300 return PTR_ERR(a);
1301
1302 tun_info = nla_data(a);
1303 tun_info->tunnel = key.tun_key;
1304
1284 add_nested_action_end(*sfa, start); 1305 add_nested_action_end(*sfa, start);
1285 1306
1286 return err; 1307 return err;
@@ -1563,17 +1584,20 @@ static int set_action_to_attr(const struct nlattr *a, struct sk_buff *skb)
1563 int err; 1584 int err;
1564 1585
1565 switch (key_type) { 1586 switch (key_type) {
1566 case OVS_KEY_ATTR_IPV4_TUNNEL: 1587 case OVS_KEY_ATTR_TUNNEL_INFO: {
1588 struct ovs_tunnel_info *tun_info = nla_data(ovs_key);
1589
1567 start = nla_nest_start(skb, OVS_ACTION_ATTR_SET); 1590 start = nla_nest_start(skb, OVS_ACTION_ATTR_SET);
1568 if (!start) 1591 if (!start)
1569 return -EMSGSIZE; 1592 return -EMSGSIZE;
1570 1593
1571 err = ipv4_tun_to_nlattr(skb, nla_data(ovs_key), 1594 err = ipv4_tun_to_nlattr(skb, &tun_info->tunnel,
1572 nla_data(ovs_key)); 1595 nla_data(ovs_key));
1573 if (err) 1596 if (err)
1574 return err; 1597 return err;
1575 nla_nest_end(skb, start); 1598 nla_nest_end(skb, start);
1576 break; 1599 break;
1600 }
1577 default: 1601 default:
1578 if (nla_put(skb, OVS_ACTION_ATTR_SET, nla_len(a), ovs_key)) 1602 if (nla_put(skb, OVS_ACTION_ATTR_SET, nla_len(a), ovs_key))
1579 return -EMSGSIZE; 1603 return -EMSGSIZE;
diff --git a/net/openvswitch/vport-gre.c b/net/openvswitch/vport-gre.c
index 309cca6e816f..fe768bd600eb 100644
--- a/net/openvswitch/vport-gre.c
+++ b/net/openvswitch/vport-gre.c
@@ -63,8 +63,10 @@ static __be16 filter_tnl_flags(__be16 flags)
63static struct sk_buff *__build_header(struct sk_buff *skb, 63static struct sk_buff *__build_header(struct sk_buff *skb,
64 int tunnel_hlen) 64 int tunnel_hlen)
65{ 65{
66 const struct ovs_key_ipv4_tunnel *tun_key = OVS_CB(skb)->egress_tun_key;
67 struct tnl_ptk_info tpi; 66 struct tnl_ptk_info tpi;
67 const struct ovs_key_ipv4_tunnel *tun_key;
68
69 tun_key = &OVS_CB(skb)->egress_tun_info->tunnel;
68 70
69 skb = gre_handle_offloads(skb, !!(tun_key->tun_flags & TUNNEL_CSUM)); 71 skb = gre_handle_offloads(skb, !!(tun_key->tun_flags & TUNNEL_CSUM));
70 if (IS_ERR(skb)) 72 if (IS_ERR(skb))
@@ -92,7 +94,7 @@ static __be64 key_to_tunnel_id(__be32 key, __be32 seq)
92static int gre_rcv(struct sk_buff *skb, 94static int gre_rcv(struct sk_buff *skb,
93 const struct tnl_ptk_info *tpi) 95 const struct tnl_ptk_info *tpi)
94{ 96{
95 struct ovs_key_ipv4_tunnel tun_key; 97 struct ovs_tunnel_info tun_info;
96 struct ovs_net *ovs_net; 98 struct ovs_net *ovs_net;
97 struct vport *vport; 99 struct vport *vport;
98 __be64 key; 100 __be64 key;
@@ -103,10 +105,10 @@ static int gre_rcv(struct sk_buff *skb,
103 return PACKET_REJECT; 105 return PACKET_REJECT;
104 106
105 key = key_to_tunnel_id(tpi->key, tpi->seq); 107 key = key_to_tunnel_id(tpi->key, tpi->seq);
106 ovs_flow_tun_key_init(&tun_key, ip_hdr(skb), key, 108 ovs_flow_tun_info_init(&tun_info, ip_hdr(skb), key,
107 filter_tnl_flags(tpi->flags)); 109 filter_tnl_flags(tpi->flags));
108 110
109 ovs_vport_receive(vport, skb, &tun_key); 111 ovs_vport_receive(vport, skb, &tun_info);
110 return PACKET_RCVD; 112 return PACKET_RCVD;
111} 113}
112 114
@@ -137,12 +139,12 @@ static int gre_tnl_send(struct vport *vport, struct sk_buff *skb)
137 __be16 df; 139 __be16 df;
138 int err; 140 int err;
139 141
140 if (unlikely(!OVS_CB(skb)->egress_tun_key)) { 142 if (unlikely(!OVS_CB(skb)->egress_tun_info)) {
141 err = -EINVAL; 143 err = -EINVAL;
142 goto error; 144 goto error;
143 } 145 }
144 146
145 tun_key = OVS_CB(skb)->egress_tun_key; 147 tun_key = &OVS_CB(skb)->egress_tun_info->tunnel;
146 /* Route lookup */ 148 /* Route lookup */
147 memset(&fl, 0, sizeof(fl)); 149 memset(&fl, 0, sizeof(fl));
148 fl.daddr = tun_key->ipv4_dst; 150 fl.daddr = tun_key->ipv4_dst;
diff --git a/net/openvswitch/vport-vxlan.c b/net/openvswitch/vport-vxlan.c
index f19539bb8adc..5fbff2c1ee49 100644
--- a/net/openvswitch/vport-vxlan.c
+++ b/net/openvswitch/vport-vxlan.c
@@ -58,7 +58,7 @@ static inline struct vxlan_port *vxlan_vport(const struct vport *vport)
58/* Called with rcu_read_lock and BH disabled. */ 58/* Called with rcu_read_lock and BH disabled. */
59static void vxlan_rcv(struct vxlan_sock *vs, struct sk_buff *skb, __be32 vx_vni) 59static void vxlan_rcv(struct vxlan_sock *vs, struct sk_buff *skb, __be32 vx_vni)
60{ 60{
61 struct ovs_key_ipv4_tunnel tun_key; 61 struct ovs_tunnel_info tun_info;
62 struct vport *vport = vs->data; 62 struct vport *vport = vs->data;
63 struct iphdr *iph; 63 struct iphdr *iph;
64 __be64 key; 64 __be64 key;
@@ -66,9 +66,9 @@ static void vxlan_rcv(struct vxlan_sock *vs, struct sk_buff *skb, __be32 vx_vni)
66 /* Save outer tunnel values */ 66 /* Save outer tunnel values */
67 iph = ip_hdr(skb); 67 iph = ip_hdr(skb);
68 key = cpu_to_be64(ntohl(vx_vni) >> 8); 68 key = cpu_to_be64(ntohl(vx_vni) >> 8);
69 ovs_flow_tun_key_init(&tun_key, iph, key, TUNNEL_KEY); 69 ovs_flow_tun_info_init(&tun_info, iph, key, TUNNEL_KEY);
70 70
71 ovs_vport_receive(vport, skb, &tun_key); 71 ovs_vport_receive(vport, skb, &tun_info);
72} 72}
73 73
74static int vxlan_get_options(const struct vport *vport, struct sk_buff *skb) 74static int vxlan_get_options(const struct vport *vport, struct sk_buff *skb)
@@ -147,12 +147,12 @@ static int vxlan_tnl_send(struct vport *vport, struct sk_buff *skb)
147 __be16 df; 147 __be16 df;
148 int err; 148 int err;
149 149
150 if (unlikely(!OVS_CB(skb)->egress_tun_key)) { 150 if (unlikely(!OVS_CB(skb)->egress_tun_info)) {
151 err = -EINVAL; 151 err = -EINVAL;
152 goto error; 152 goto error;
153 } 153 }
154 154
155 tun_key = OVS_CB(skb)->egress_tun_key; 155 tun_key = &OVS_CB(skb)->egress_tun_info->tunnel;
156 /* Route lookup */ 156 /* Route lookup */
157 memset(&fl, 0, sizeof(fl)); 157 memset(&fl, 0, sizeof(fl));
158 fl.daddr = tun_key->ipv4_dst; 158 fl.daddr = tun_key->ipv4_dst;
diff --git a/net/openvswitch/vport.c b/net/openvswitch/vport.c
index 5df8377fcfb1..3e50ee8a218c 100644
--- a/net/openvswitch/vport.c
+++ b/net/openvswitch/vport.c
@@ -432,7 +432,7 @@ u32 ovs_vport_find_upcall_portid(const struct vport *p, struct sk_buff *skb)
432 * skb->data should point to the Ethernet header. 432 * skb->data should point to the Ethernet header.
433 */ 433 */
434void ovs_vport_receive(struct vport *vport, struct sk_buff *skb, 434void ovs_vport_receive(struct vport *vport, struct sk_buff *skb,
435 struct ovs_key_ipv4_tunnel *tun_key) 435 struct ovs_tunnel_info *tun_info)
436{ 436{
437 struct pcpu_sw_netstats *stats; 437 struct pcpu_sw_netstats *stats;
438 struct sw_flow_key key; 438 struct sw_flow_key key;
@@ -445,9 +445,9 @@ void ovs_vport_receive(struct vport *vport, struct sk_buff *skb,
445 u64_stats_update_end(&stats->syncp); 445 u64_stats_update_end(&stats->syncp);
446 446
447 OVS_CB(skb)->input_vport = vport; 447 OVS_CB(skb)->input_vport = vport;
448 OVS_CB(skb)->egress_tun_key = NULL; 448 OVS_CB(skb)->egress_tun_info = NULL;
449 /* Extract flow from 'skb' into 'key'. */ 449 /* Extract flow from 'skb' into 'key'. */
450 error = ovs_flow_key_extract(tun_key, skb, &key); 450 error = ovs_flow_key_extract(tun_info, skb, &key);
451 if (unlikely(error)) { 451 if (unlikely(error)) {
452 kfree_skb(skb); 452 kfree_skb(skb);
453 return; 453 return;
diff --git a/net/openvswitch/vport.h b/net/openvswitch/vport.h
index 0efd62fef1e8..e28964aba021 100644
--- a/net/openvswitch/vport.h
+++ b/net/openvswitch/vport.h
@@ -207,7 +207,7 @@ static inline struct vport *vport_from_priv(void *priv)
207} 207}
208 208
209void ovs_vport_receive(struct vport *, struct sk_buff *, 209void ovs_vport_receive(struct vport *, struct sk_buff *,
210 struct ovs_key_ipv4_tunnel *); 210 struct ovs_tunnel_info *);
211 211
212/* List of statically compiled vport implementations. Don't forget to also 212/* List of statically compiled vport implementations. Don't forget to also
213 * add yours to the list at the top of vport.c. */ 213 * add yours to the list at the top of vport.c. */