aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/bridge/br_device.c4
-rw-r--r--net/bridge/br_if.c3
-rw-r--r--net/core/dev.c33
-rw-r--r--net/core/skbuff.c5
-rw-r--r--net/ipv4/af_inet.c6
-rw-r--r--net/ipv4/tcp.c8
6 files changed, 40 insertions, 19 deletions
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 2afdc7c0736c..f8dbcee80eba 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -184,6 +184,6 @@ void br_dev_setup(struct net_device *dev)
184 dev->set_mac_address = br_set_mac_address; 184 dev->set_mac_address = br_set_mac_address;
185 dev->priv_flags = IFF_EBRIDGE; 185 dev->priv_flags = IFF_EBRIDGE;
186 186
187 dev->features = NETIF_F_SG | NETIF_F_FRAGLIST 187 dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA |
188 | NETIF_F_HIGHDMA | NETIF_F_TSO | NETIF_F_NO_CSUM; 188 NETIF_F_TSO | NETIF_F_NO_CSUM | NETIF_F_GSO_ROBUST;
189} 189}
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 07956ecf545e..f55ef682ef84 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -392,7 +392,8 @@ void br_features_recompute(struct net_bridge *br)
392 features &= feature; 392 features &= feature;
393 } 393 }
394 394
395 br->dev->features = features | checksum | NETIF_F_LLTX; 395 br->dev->features = features | checksum | NETIF_F_LLTX |
396 NETIF_F_GSO_ROBUST;
396} 397}
397 398
398/* called with RTNL */ 399/* called with RTNL */
diff --git a/net/core/dev.c b/net/core/dev.c
index f1c52cbd6ef7..4f2014994a84 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1190,11 +1190,14 @@ out:
1190/** 1190/**
1191 * skb_gso_segment - Perform segmentation on skb. 1191 * skb_gso_segment - Perform segmentation on skb.
1192 * @skb: buffer to segment 1192 * @skb: buffer to segment
1193 * @sg: whether scatter-gather is supported on the target. 1193 * @features: features for the output path (see dev->features)
1194 * 1194 *
1195 * This function segments the given skb and returns a list of segments. 1195 * This function segments the given skb and returns a list of segments.
1196 *
1197 * It may return NULL if the skb requires no segmentation. This is
1198 * only possible when GSO is used for verifying header integrity.
1196 */ 1199 */
1197struct sk_buff *skb_gso_segment(struct sk_buff *skb, int sg) 1200struct sk_buff *skb_gso_segment(struct sk_buff *skb, int features)
1198{ 1201{
1199 struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT); 1202 struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT);
1200 struct packet_type *ptype; 1203 struct packet_type *ptype;
@@ -1210,12 +1213,14 @@ struct sk_buff *skb_gso_segment(struct sk_buff *skb, int sg)
1210 rcu_read_lock(); 1213 rcu_read_lock();
1211 list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type) & 15], list) { 1214 list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type) & 15], list) {
1212 if (ptype->type == type && !ptype->dev && ptype->gso_segment) { 1215 if (ptype->type == type && !ptype->dev && ptype->gso_segment) {
1213 segs = ptype->gso_segment(skb, sg); 1216 segs = ptype->gso_segment(skb, features);
1214 break; 1217 break;
1215 } 1218 }
1216 } 1219 }
1217 rcu_read_unlock(); 1220 rcu_read_unlock();
1218 1221
1222 __skb_push(skb, skb->data - skb->mac.raw);
1223
1219 return segs; 1224 return segs;
1220} 1225}
1221 1226
@@ -1291,9 +1296,15 @@ static int dev_gso_segment(struct sk_buff *skb)
1291{ 1296{
1292 struct net_device *dev = skb->dev; 1297 struct net_device *dev = skb->dev;
1293 struct sk_buff *segs; 1298 struct sk_buff *segs;
1299 int features = dev->features & ~(illegal_highdma(dev, skb) ?
1300 NETIF_F_SG : 0);
1301
1302 segs = skb_gso_segment(skb, features);
1303
1304 /* Verifying header integrity only. */
1305 if (!segs)
1306 return 0;
1294 1307
1295 segs = skb_gso_segment(skb, dev->features & NETIF_F_SG &&
1296 !illegal_highdma(dev, skb));
1297 if (unlikely(IS_ERR(segs))) 1308 if (unlikely(IS_ERR(segs)))
1298 return PTR_ERR(segs); 1309 return PTR_ERR(segs);
1299 1310
@@ -1310,13 +1321,17 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
1310 if (netdev_nit) 1321 if (netdev_nit)
1311 dev_queue_xmit_nit(skb, dev); 1322 dev_queue_xmit_nit(skb, dev);
1312 1323
1313 if (!netif_needs_gso(dev, skb)) 1324 if (netif_needs_gso(dev, skb)) {
1314 return dev->hard_start_xmit(skb, dev); 1325 if (unlikely(dev_gso_segment(skb)))
1326 goto out_kfree_skb;
1327 if (skb->next)
1328 goto gso;
1329 }
1315 1330
1316 if (unlikely(dev_gso_segment(skb))) 1331 return dev->hard_start_xmit(skb, dev);
1317 goto out_kfree_skb;
1318 } 1332 }
1319 1333
1334gso:
1320 do { 1335 do {
1321 struct sk_buff *nskb = skb->next; 1336 struct sk_buff *nskb = skb->next;
1322 int rc; 1337 int rc;
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 6edbb90cbcec..dfef9eece83e 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -1848,13 +1848,13 @@ EXPORT_SYMBOL_GPL(skb_pull_rcsum);
1848/** 1848/**
1849 * skb_segment - Perform protocol segmentation on skb. 1849 * skb_segment - Perform protocol segmentation on skb.
1850 * @skb: buffer to segment 1850 * @skb: buffer to segment
1851 * @sg: whether scatter-gather can be used for generated segments 1851 * @features: features for the output path (see dev->features)
1852 * 1852 *
1853 * This function performs segmentation on the given skb. It returns 1853 * This function performs segmentation on the given skb. It returns
1854 * the segment at the given position. It returns NULL if there are 1854 * the segment at the given position. It returns NULL if there are
1855 * no more segments to generate, or when an error is encountered. 1855 * no more segments to generate, or when an error is encountered.
1856 */ 1856 */
1857struct sk_buff *skb_segment(struct sk_buff *skb, int sg) 1857struct sk_buff *skb_segment(struct sk_buff *skb, int features)
1858{ 1858{
1859 struct sk_buff *segs = NULL; 1859 struct sk_buff *segs = NULL;
1860 struct sk_buff *tail = NULL; 1860 struct sk_buff *tail = NULL;
@@ -1863,6 +1863,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int sg)
1863 unsigned int offset = doffset; 1863 unsigned int offset = doffset;
1864 unsigned int headroom; 1864 unsigned int headroom;
1865 unsigned int len; 1865 unsigned int len;
1866 int sg = features & NETIF_F_SG;
1866 int nfrags = skb_shinfo(skb)->nr_frags; 1867 int nfrags = skb_shinfo(skb)->nr_frags;
1867 int err = -ENOMEM; 1868 int err = -ENOMEM;
1868 int i = 0; 1869 int i = 0;
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 461216b47948..8d157157bf8e 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1097,7 +1097,7 @@ int inet_sk_rebuild_header(struct sock *sk)
1097 1097
1098EXPORT_SYMBOL(inet_sk_rebuild_header); 1098EXPORT_SYMBOL(inet_sk_rebuild_header);
1099 1099
1100static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int sg) 1100static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int features)
1101{ 1101{
1102 struct sk_buff *segs = ERR_PTR(-EINVAL); 1102 struct sk_buff *segs = ERR_PTR(-EINVAL);
1103 struct iphdr *iph; 1103 struct iphdr *iph;
@@ -1126,10 +1126,10 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int sg)
1126 rcu_read_lock(); 1126 rcu_read_lock();
1127 ops = rcu_dereference(inet_protos[proto]); 1127 ops = rcu_dereference(inet_protos[proto]);
1128 if (ops && ops->gso_segment) 1128 if (ops && ops->gso_segment)
1129 segs = ops->gso_segment(skb, sg); 1129 segs = ops->gso_segment(skb, features);
1130 rcu_read_unlock(); 1130 rcu_read_unlock();
1131 1131
1132 if (IS_ERR(segs)) 1132 if (!segs || unlikely(IS_ERR(segs)))
1133 goto out; 1133 goto out;
1134 1134
1135 skb = segs; 1135 skb = segs;
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index c04176be7ed1..0336422c88a0 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -2145,7 +2145,7 @@ int compat_tcp_getsockopt(struct sock *sk, int level, int optname,
2145EXPORT_SYMBOL(compat_tcp_getsockopt); 2145EXPORT_SYMBOL(compat_tcp_getsockopt);
2146#endif 2146#endif
2147 2147
2148struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int sg) 2148struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features)
2149{ 2149{
2150 struct sk_buff *segs = ERR_PTR(-EINVAL); 2150 struct sk_buff *segs = ERR_PTR(-EINVAL);
2151 struct tcphdr *th; 2151 struct tcphdr *th;
@@ -2166,10 +2166,14 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int sg)
2166 if (!pskb_may_pull(skb, thlen)) 2166 if (!pskb_may_pull(skb, thlen))
2167 goto out; 2167 goto out;
2168 2168
2169 segs = NULL;
2170 if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST))
2171 goto out;
2172
2169 oldlen = (u16)~skb->len; 2173 oldlen = (u16)~skb->len;
2170 __skb_pull(skb, thlen); 2174 __skb_pull(skb, thlen);
2171 2175
2172 segs = skb_segment(skb, sg); 2176 segs = skb_segment(skb, features);
2173 if (IS_ERR(segs)) 2177 if (IS_ERR(segs))
2174 goto out; 2178 goto out;
2175 2179