aboutsummaryrefslogtreecommitdiffstats
path: root/net/openvswitch
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2013-06-14 18:31:22 -0400
committerDavid S. Miller <davem@davemloft.net>2013-06-14 18:31:22 -0400
commit09ce069dff607f86dcdeb541d20734a8f42478c5 (patch)
tree03c7e9dc78d4dbfc2b3687053bbbd1680789934d /net/openvswitch
parent948e306d7d645af80ea331b60495710fe4fe12bb (diff)
parent93d8fd1514b6862c3370ea92be3f3b4216e0bf8f (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/jesse/openvswitch
Jesse Gross says: ==================== A few miscellaneous improvements and cleanups before the GRE tunnel integration series. Intended for net-next/3.11. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/openvswitch')
-rw-r--r--net/openvswitch/actions.c4
-rw-r--r--net/openvswitch/datapath.c17
-rw-r--r--net/openvswitch/flow.c29
-rw-r--r--net/openvswitch/flow.h4
-rw-r--r--net/openvswitch/vport-internal_dev.c1
-rw-r--r--net/openvswitch/vport-netdev.c7
-rw-r--r--net/openvswitch/vport-netdev.h1
-rw-r--r--net/openvswitch/vport.c11
-rw-r--r--net/openvswitch/vport.h13
9 files changed, 51 insertions, 36 deletions
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index 894b6cbdd929..596d6373399d 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -130,9 +130,13 @@ static int set_eth_addr(struct sk_buff *skb,
130 if (unlikely(err)) 130 if (unlikely(err))
131 return err; 131 return err;
132 132
133 skb_postpull_rcsum(skb, eth_hdr(skb), ETH_ALEN * 2);
134
133 memcpy(eth_hdr(skb)->h_source, eth_key->eth_src, ETH_ALEN); 135 memcpy(eth_hdr(skb)->h_source, eth_key->eth_src, ETH_ALEN);
134 memcpy(eth_hdr(skb)->h_dest, eth_key->eth_dst, ETH_ALEN); 136 memcpy(eth_hdr(skb)->h_dest, eth_key->eth_dst, ETH_ALEN);
135 137
138 ovs_skb_postpush_rcsum(skb, eth_hdr(skb), ETH_ALEN * 2);
139
136 return 0; 140 return 0;
137} 141}
138 142
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index d12d6b8b5e8b..0f783d9fa00d 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -739,10 +739,7 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
739 if (err) 739 if (err)
740 goto err_flow_free; 740 goto err_flow_free;
741 741
742 err = ovs_flow_metadata_from_nlattrs(&flow->key.phy.priority, 742 err = ovs_flow_metadata_from_nlattrs(flow, a[OVS_PACKET_ATTR_KEY]);
743 &flow->key.phy.skb_mark,
744 &flow->key.phy.in_port,
745 a[OVS_PACKET_ATTR_KEY]);
746 if (err) 743 if (err)
747 goto err_flow_free; 744 goto err_flow_free;
748 745
@@ -1812,10 +1809,11 @@ static int ovs_vport_cmd_set(struct sk_buff *skb, struct genl_info *info)
1812 if (IS_ERR(vport)) 1809 if (IS_ERR(vport))
1813 goto exit_unlock; 1810 goto exit_unlock;
1814 1811
1815 err = 0;
1816 if (a[OVS_VPORT_ATTR_TYPE] && 1812 if (a[OVS_VPORT_ATTR_TYPE] &&
1817 nla_get_u32(a[OVS_VPORT_ATTR_TYPE]) != vport->ops->type) 1813 nla_get_u32(a[OVS_VPORT_ATTR_TYPE]) != vport->ops->type) {
1818 err = -EINVAL; 1814 err = -EINVAL;
1815 goto exit_unlock;
1816 }
1819 1817
1820 reply = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1818 reply = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1821 if (!reply) { 1819 if (!reply) {
@@ -1823,10 +1821,11 @@ static int ovs_vport_cmd_set(struct sk_buff *skb, struct genl_info *info)
1823 goto exit_unlock; 1821 goto exit_unlock;
1824 } 1822 }
1825 1823
1826 if (!err && a[OVS_VPORT_ATTR_OPTIONS]) 1824 if (a[OVS_VPORT_ATTR_OPTIONS]) {
1827 err = ovs_vport_set_options(vport, a[OVS_VPORT_ATTR_OPTIONS]); 1825 err = ovs_vport_set_options(vport, a[OVS_VPORT_ATTR_OPTIONS]);
1828 if (err) 1826 if (err)
1829 goto exit_free; 1827 goto exit_free;
1828 }
1830 1829
1831 if (a[OVS_VPORT_ATTR_UPCALL_PID]) 1830 if (a[OVS_VPORT_ATTR_UPCALL_PID])
1832 vport->upcall_portid = nla_get_u32(a[OVS_VPORT_ATTR_UPCALL_PID]); 1831 vport->upcall_portid = nla_get_u32(a[OVS_VPORT_ATTR_UPCALL_PID]);
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index b15321a2228c..093c191d4fc2 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -590,10 +590,10 @@ out:
590 * - skb->network_header: just past the Ethernet header, or just past the 590 * - skb->network_header: just past the Ethernet header, or just past the
591 * VLAN header, to the first byte of the Ethernet payload. 591 * VLAN header, to the first byte of the Ethernet payload.
592 * 592 *
593 * - skb->transport_header: If key->dl_type is ETH_P_IP or ETH_P_IPV6 593 * - skb->transport_header: If key->eth.type is ETH_P_IP or ETH_P_IPV6
594 * on output, then just past the IP header, if one is present and 594 * on output, then just past the IP header, if one is present and
595 * of a correct length, otherwise the same as skb->network_header. 595 * of a correct length, otherwise the same as skb->network_header.
596 * For other key->dl_type values it is left untouched. 596 * For other key->eth.type values it is left untouched.
597 */ 597 */
598int ovs_flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key, 598int ovs_flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key,
599 int *key_lenp) 599 int *key_lenp)
@@ -618,6 +618,9 @@ int ovs_flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key,
618 memcpy(key->eth.dst, eth->h_dest, ETH_ALEN); 618 memcpy(key->eth.dst, eth->h_dest, ETH_ALEN);
619 619
620 __skb_pull(skb, 2 * ETH_ALEN); 620 __skb_pull(skb, 2 * ETH_ALEN);
621 /* We are going to push all headers that we pull, so no need to
622 * update skb->csum here.
623 */
621 624
622 if (vlan_tx_tag_present(skb)) 625 if (vlan_tx_tag_present(skb))
623 key->eth.tci = htons(skb->vlan_tci); 626 key->eth.tci = htons(skb->vlan_tci);
@@ -1122,10 +1125,8 @@ int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp,
1122 1125
1123/** 1126/**
1124 * ovs_flow_metadata_from_nlattrs - parses Netlink attributes into a flow key. 1127 * ovs_flow_metadata_from_nlattrs - parses Netlink attributes into a flow key.
1125 * @priority: receives the skb priority 1128 * @flow: Receives extracted in_port, priority, tun_key and skb_mark.
1126 * @mark: receives the skb mark 1129 * @attr: Netlink attribute holding nested %OVS_KEY_ATTR_* Netlink attribute
1127 * @in_port: receives the extracted input port.
1128 * @key: Netlink attribute holding nested %OVS_KEY_ATTR_* Netlink attribute
1129 * sequence. 1130 * sequence.
1130 * 1131 *
1131 * This parses a series of Netlink attributes that form a flow key, which must 1132 * This parses a series of Netlink attributes that form a flow key, which must
@@ -1133,15 +1134,15 @@ int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp,
1133 * get the metadata, that is, the parts of the flow key that cannot be 1134 * get the metadata, that is, the parts of the flow key that cannot be
1134 * extracted from the packet itself. 1135 * extracted from the packet itself.
1135 */ 1136 */
1136int ovs_flow_metadata_from_nlattrs(u32 *priority, u32 *mark, u16 *in_port, 1137int ovs_flow_metadata_from_nlattrs(struct sw_flow *flow,
1137 const struct nlattr *attr) 1138 const struct nlattr *attr)
1138{ 1139{
1139 const struct nlattr *nla; 1140 const struct nlattr *nla;
1140 int rem; 1141 int rem;
1141 1142
1142 *in_port = DP_MAX_PORTS; 1143 flow->key.phy.in_port = DP_MAX_PORTS;
1143 *priority = 0; 1144 flow->key.phy.priority = 0;
1144 *mark = 0; 1145 flow->key.phy.skb_mark = 0;
1145 1146
1146 nla_for_each_nested(nla, attr, rem) { 1147 nla_for_each_nested(nla, attr, rem) {
1147 int type = nla_type(nla); 1148 int type = nla_type(nla);
@@ -1152,17 +1153,17 @@ int ovs_flow_metadata_from_nlattrs(u32 *priority, u32 *mark, u16 *in_port,
1152 1153
1153 switch (type) { 1154 switch (type) {
1154 case OVS_KEY_ATTR_PRIORITY: 1155 case OVS_KEY_ATTR_PRIORITY:
1155 *priority = nla_get_u32(nla); 1156 flow->key.phy.priority = nla_get_u32(nla);
1156 break; 1157 break;
1157 1158
1158 case OVS_KEY_ATTR_IN_PORT: 1159 case OVS_KEY_ATTR_IN_PORT:
1159 if (nla_get_u32(nla) >= DP_MAX_PORTS) 1160 if (nla_get_u32(nla) >= DP_MAX_PORTS)
1160 return -EINVAL; 1161 return -EINVAL;
1161 *in_port = nla_get_u32(nla); 1162 flow->key.phy.in_port = nla_get_u32(nla);
1162 break; 1163 break;
1163 1164
1164 case OVS_KEY_ATTR_SKB_MARK: 1165 case OVS_KEY_ATTR_SKB_MARK:
1165 *mark = nla_get_u32(nla); 1166 flow->key.phy.skb_mark = nla_get_u32(nla);
1166 break; 1167 break;
1167 } 1168 }
1168 } 1169 }
diff --git a/net/openvswitch/flow.h b/net/openvswitch/flow.h
index 0875fde65b9c..2a83e2141f08 100644
--- a/net/openvswitch/flow.h
+++ b/net/openvswitch/flow.h
@@ -141,8 +141,8 @@ u64 ovs_flow_used_time(unsigned long flow_jiffies);
141int ovs_flow_to_nlattrs(const struct sw_flow_key *, struct sk_buff *); 141int ovs_flow_to_nlattrs(const struct sw_flow_key *, struct sk_buff *);
142int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp, 142int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp,
143 const struct nlattr *); 143 const struct nlattr *);
144int ovs_flow_metadata_from_nlattrs(u32 *priority, u32 *mark, u16 *in_port, 144int ovs_flow_metadata_from_nlattrs(struct sw_flow *flow,
145 const struct nlattr *); 145 const struct nlattr *attr);
146 146
147#define MAX_ACTIONS_BUFSIZE (16 * 1024) 147#define MAX_ACTIONS_BUFSIZE (16 * 1024)
148#define TBL_MIN_BUCKETS 1024 148#define TBL_MIN_BUCKETS 1024
diff --git a/net/openvswitch/vport-internal_dev.c b/net/openvswitch/vport-internal_dev.c
index 84e0a0379186..e284c7e1fec4 100644
--- a/net/openvswitch/vport-internal_dev.c
+++ b/net/openvswitch/vport-internal_dev.c
@@ -221,6 +221,7 @@ static int internal_dev_recv(struct vport *vport, struct sk_buff *skb)
221 skb->dev = netdev; 221 skb->dev = netdev;
222 skb->pkt_type = PACKET_HOST; 222 skb->pkt_type = PACKET_HOST;
223 skb->protocol = eth_type_trans(skb, netdev); 223 skb->protocol = eth_type_trans(skb, netdev);
224 skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN);
224 225
225 netif_rx(skb); 226 netif_rx(skb);
226 227
diff --git a/net/openvswitch/vport-netdev.c b/net/openvswitch/vport-netdev.c
index 4f01c6d2ffa4..40de815b4213 100644
--- a/net/openvswitch/vport-netdev.c
+++ b/net/openvswitch/vport-netdev.c
@@ -49,6 +49,8 @@ static void netdev_port_receive(struct vport *vport, struct sk_buff *skb)
49 return; 49 return;
50 50
51 skb_push(skb, ETH_HLEN); 51 skb_push(skb, ETH_HLEN);
52 ovs_skb_postpush_rcsum(skb, skb->data, ETH_HLEN);
53
52 ovs_vport_receive(vport, skb); 54 ovs_vport_receive(vport, skb);
53 return; 55 return;
54 56
@@ -170,7 +172,7 @@ static int netdev_send(struct vport *vport, struct sk_buff *skb)
170 net_warn_ratelimited("%s: dropped over-mtu packet: %d > %d\n", 172 net_warn_ratelimited("%s: dropped over-mtu packet: %d > %d\n",
171 netdev_vport->dev->name, 173 netdev_vport->dev->name,
172 packet_length(skb), mtu); 174 packet_length(skb), mtu);
173 goto error; 175 goto drop;
174 } 176 }
175 177
176 skb->dev = netdev_vport->dev; 178 skb->dev = netdev_vport->dev;
@@ -179,9 +181,8 @@ static int netdev_send(struct vport *vport, struct sk_buff *skb)
179 181
180 return len; 182 return len;
181 183
182error: 184drop:
183 kfree_skb(skb); 185 kfree_skb(skb);
184 ovs_vport_record_error(vport, VPORT_E_TX_DROPPED);
185 return 0; 186 return 0;
186} 187}
187 188
diff --git a/net/openvswitch/vport-netdev.h b/net/openvswitch/vport-netdev.h
index a3cb3a32cd77..dd298b5c5cdb 100644
--- a/net/openvswitch/vport-netdev.h
+++ b/net/openvswitch/vport-netdev.h
@@ -39,6 +39,5 @@ netdev_vport_priv(const struct vport *vport)
39} 39}
40 40
41const char *ovs_netdev_get_name(const struct vport *); 41const char *ovs_netdev_get_name(const struct vport *);
42const char *ovs_netdev_get_config(const struct vport *);
43 42
44#endif /* vport_netdev.h */ 43#endif /* vport_netdev.h */
diff --git a/net/openvswitch/vport.c b/net/openvswitch/vport.c
index 720623190eaa..176d449351eb 100644
--- a/net/openvswitch/vport.c
+++ b/net/openvswitch/vport.c
@@ -351,7 +351,7 @@ int ovs_vport_send(struct vport *vport, struct sk_buff *skb)
351{ 351{
352 int sent = vport->ops->send(vport, skb); 352 int sent = vport->ops->send(vport, skb);
353 353
354 if (likely(sent)) { 354 if (likely(sent > 0)) {
355 struct pcpu_tstats *stats; 355 struct pcpu_tstats *stats;
356 356
357 stats = this_cpu_ptr(vport->percpu_stats); 357 stats = this_cpu_ptr(vport->percpu_stats);
@@ -360,7 +360,12 @@ int ovs_vport_send(struct vport *vport, struct sk_buff *skb)
360 stats->tx_packets++; 360 stats->tx_packets++;
361 stats->tx_bytes += sent; 361 stats->tx_bytes += sent;
362 u64_stats_update_end(&stats->syncp); 362 u64_stats_update_end(&stats->syncp);
363 } 363 } else if (sent < 0) {
364 ovs_vport_record_error(vport, VPORT_E_TX_ERROR);
365 kfree_skb(skb);
366 } else
367 ovs_vport_record_error(vport, VPORT_E_TX_DROPPED);
368
364 return sent; 369 return sent;
365} 370}
366 371
@@ -371,7 +376,7 @@ int ovs_vport_send(struct vport *vport, struct sk_buff *skb)
371 * @err_type: one of enum vport_err_type types to indicate the error type 376 * @err_type: one of enum vport_err_type types to indicate the error type
372 * 377 *
373 * If using the vport generic stats layer indicate that an error of the given 378 * If using the vport generic stats layer indicate that an error of the given
374 * type has occured. 379 * type has occurred.
375 */ 380 */
376void ovs_vport_record_error(struct vport *vport, enum vport_err_type err_type) 381void ovs_vport_record_error(struct vport *vport, enum vport_err_type err_type)
377{ 382{
diff --git a/net/openvswitch/vport.h b/net/openvswitch/vport.h
index 68a377bc0841..293278c4c2df 100644
--- a/net/openvswitch/vport.h
+++ b/net/openvswitch/vport.h
@@ -123,9 +123,8 @@ struct vport_parms {
123 * existing vport to a &struct sk_buff. May be %NULL for a vport that does not 123 * existing vport to a &struct sk_buff. May be %NULL for a vport that does not
124 * have any configuration. 124 * have any configuration.
125 * @get_name: Get the device's name. 125 * @get_name: Get the device's name.
126 * @get_config: Get the device's configuration. 126 * @send: Send a packet on the device. Returns the length of the packet sent,
127 * May be null if the device does not have an ifindex. 127 * zero for dropped packets or negative for error.
128 * @send: Send a packet on the device. Returns the length of the packet sent.
129 */ 128 */
130struct vport_ops { 129struct vport_ops {
131 enum ovs_vport_type type; 130 enum ovs_vport_type type;
@@ -139,7 +138,6 @@ struct vport_ops {
139 138
140 /* Called with rcu_read_lock or ovs_mutex. */ 139 /* Called with rcu_read_lock or ovs_mutex. */
141 const char *(*get_name)(const struct vport *); 140 const char *(*get_name)(const struct vport *);
142 void (*get_config)(const struct vport *, void *);
143 141
144 int (*send)(struct vport *, struct sk_buff *); 142 int (*send)(struct vport *, struct sk_buff *);
145}; 143};
@@ -194,4 +192,11 @@ void ovs_vport_record_error(struct vport *, enum vport_err_type err_type);
194extern const struct vport_ops ovs_netdev_vport_ops; 192extern const struct vport_ops ovs_netdev_vport_ops;
195extern const struct vport_ops ovs_internal_vport_ops; 193extern const struct vport_ops ovs_internal_vport_ops;
196 194
195static inline void ovs_skb_postpush_rcsum(struct sk_buff *skb,
196 const void *start, unsigned int len)
197{
198 if (skb->ip_summed == CHECKSUM_COMPLETE)
199 skb->csum = csum_add(skb->csum, csum_partial(start, len, 0));
200}
201
197#endif /* vport.h */ 202#endif /* vport.h */