Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 31327
b: refs/heads/master
c: 576a30e
h: refs/heads/master
i:
  31325: ccf2c84
  31323: 76dca91
  31319: 401f5c8
  31311: 445a245
  31295: c665ac1
v: v3
  • Loading branch information
Herbert Xu authored and David S. Miller committed Jun 29, 2006
1 parent 7a0b05d commit 939a67a
Show file tree
Hide file tree
Showing 11 changed files with 60 additions and 28 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 68c1692e3ea5d79f24cb5cc566c4a73939d13d25
refs/heads/master: 576a30eb6453439b3c37ba24455ac7090c247b5a
17 changes: 12 additions & 5 deletions trunk/include/linux/netdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,7 @@ struct net_device
#define NETIF_F_GSO_SHIFT 16
#define NETIF_F_TSO (SKB_GSO_TCPV4 << NETIF_F_GSO_SHIFT)
#define NETIF_F_UFO (SKB_GSO_UDPV4 << NETIF_F_GSO_SHIFT)
#define NETIF_F_GSO_ROBUST (SKB_GSO_DODGY << NETIF_F_GSO_SHIFT)

#define NETIF_F_GEN_CSUM (NETIF_F_NO_CSUM | NETIF_F_HW_CSUM)
#define NETIF_F_ALL_CSUM (NETIF_F_IP_CSUM | NETIF_F_GEN_CSUM)
Expand Down Expand Up @@ -543,7 +544,8 @@ struct packet_type {
struct net_device *,
struct packet_type *,
struct net_device *);
struct sk_buff *(*gso_segment)(struct sk_buff *skb, int sg);
struct sk_buff *(*gso_segment)(struct sk_buff *skb,
int features);
void *af_packet_priv;
struct list_head list;
};
Expand Down Expand Up @@ -968,7 +970,7 @@ extern int netdev_max_backlog;
extern int weight_p;
extern int netdev_set_master(struct net_device *dev, struct net_device *master);
extern int skb_checksum_help(struct sk_buff *skb, int inward);
extern struct sk_buff *skb_gso_segment(struct sk_buff *skb, int sg);
extern struct sk_buff *skb_gso_segment(struct sk_buff *skb, int features);
#ifdef CONFIG_BUG
extern void netdev_rx_csum_fault(struct net_device *dev);
#else
Expand All @@ -988,11 +990,16 @@ extern void dev_seq_stop(struct seq_file *seq, void *v);

extern void linkwatch_run_queue(void);

static inline int skb_gso_ok(struct sk_buff *skb, int features)
{
int feature = skb_shinfo(skb)->gso_size ?
skb_shinfo(skb)->gso_type << NETIF_F_GSO_SHIFT : 0;
return (features & feature) != feature;
}

static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb)
{
int feature = skb_shinfo(skb)->gso_type << NETIF_F_GSO_SHIFT;
return skb_shinfo(skb)->gso_size &&
(dev->features & feature) != feature;
return skb_gso_ok(skb, dev->features);
}

#endif /* __KERNEL__ */
Expand Down
5 changes: 4 additions & 1 deletion trunk/include/linux/skbuff.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,9 @@ enum {
enum {
SKB_GSO_TCPV4 = 1 << 0,
SKB_GSO_UDPV4 = 1 << 1,

/* This indicates the skb is from an untrusted source. */
SKB_GSO_DODGY = 1 << 2,
};

/**
Expand Down Expand Up @@ -1299,7 +1302,7 @@ extern void skb_split(struct sk_buff *skb,
struct sk_buff *skb1, const u32 len);

extern void skb_release_data(struct sk_buff *skb);
extern struct sk_buff *skb_segment(struct sk_buff *skb, int sg);
extern struct sk_buff *skb_segment(struct sk_buff *skb, int features);

static inline void *skb_header_pointer(const struct sk_buff *skb, int offset,
int len, void *buffer)
Expand Down
3 changes: 2 additions & 1 deletion trunk/include/net/protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@
struct net_protocol {
int (*handler)(struct sk_buff *skb);
void (*err_handler)(struct sk_buff *skb, u32 info);
struct sk_buff *(*gso_segment)(struct sk_buff *skb, int sg);
struct sk_buff *(*gso_segment)(struct sk_buff *skb,
int features);
int no_policy;
};

Expand Down
2 changes: 1 addition & 1 deletion trunk/include/net/tcp.h
Original file line number Diff line number Diff line change
Expand Up @@ -1086,7 +1086,7 @@ extern struct request_sock_ops tcp_request_sock_ops;

extern int tcp_v4_destroy_sock(struct sock *sk);

extern struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int sg);
extern struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features);

#ifdef CONFIG_PROC_FS
extern int tcp4_proc_init(void);
Expand Down
4 changes: 2 additions & 2 deletions trunk/net/bridge/br_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,6 @@ void br_dev_setup(struct net_device *dev)
dev->set_mac_address = br_set_mac_address;
dev->priv_flags = IFF_EBRIDGE;

dev->features = NETIF_F_SG | NETIF_F_FRAGLIST
| NETIF_F_HIGHDMA | NETIF_F_TSO | NETIF_F_NO_CSUM;
dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA |
NETIF_F_TSO | NETIF_F_NO_CSUM | NETIF_F_GSO_ROBUST;
}
3 changes: 2 additions & 1 deletion trunk/net/bridge/br_if.c
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,8 @@ void br_features_recompute(struct net_bridge *br)
features &= feature;
}

br->dev->features = features | checksum | NETIF_F_LLTX;
br->dev->features = features | checksum | NETIF_F_LLTX |
NETIF_F_GSO_ROBUST;
}

/* called with RTNL */
Expand Down
33 changes: 24 additions & 9 deletions trunk/net/core/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -1190,11 +1190,14 @@ int skb_checksum_help(struct sk_buff *skb, int inward)
/**
* skb_gso_segment - Perform segmentation on skb.
* @skb: buffer to segment
* @sg: whether scatter-gather is supported on the target.
* @features: features for the output path (see dev->features)
*
* This function segments the given skb and returns a list of segments.
*
* It may return NULL if the skb requires no segmentation. This is
* only possible when GSO is used for verifying header integrity.
*/
struct sk_buff *skb_gso_segment(struct sk_buff *skb, int sg)
struct sk_buff *skb_gso_segment(struct sk_buff *skb, int features)
{
struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT);
struct packet_type *ptype;
Expand All @@ -1210,12 +1213,14 @@ struct sk_buff *skb_gso_segment(struct sk_buff *skb, int sg)
rcu_read_lock();
list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type) & 15], list) {
if (ptype->type == type && !ptype->dev && ptype->gso_segment) {
segs = ptype->gso_segment(skb, sg);
segs = ptype->gso_segment(skb, features);
break;
}
}
rcu_read_unlock();

__skb_push(skb, skb->data - skb->mac.raw);

return segs;
}

Expand Down Expand Up @@ -1291,9 +1296,15 @@ static int dev_gso_segment(struct sk_buff *skb)
{
struct net_device *dev = skb->dev;
struct sk_buff *segs;
int features = dev->features & ~(illegal_highdma(dev, skb) ?
NETIF_F_SG : 0);

segs = skb_gso_segment(skb, features);

/* Verifying header integrity only. */
if (!segs)
return 0;

segs = skb_gso_segment(skb, dev->features & NETIF_F_SG &&
!illegal_highdma(dev, skb));
if (unlikely(IS_ERR(segs)))
return PTR_ERR(segs);

Expand All @@ -1310,13 +1321,17 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (netdev_nit)
dev_queue_xmit_nit(skb, dev);

if (!netif_needs_gso(dev, skb))
return dev->hard_start_xmit(skb, dev);
if (netif_needs_gso(dev, skb)) {
if (unlikely(dev_gso_segment(skb)))
goto out_kfree_skb;
if (skb->next)
goto gso;
}

if (unlikely(dev_gso_segment(skb)))
goto out_kfree_skb;
return dev->hard_start_xmit(skb, dev);
}

gso:
do {
struct sk_buff *nskb = skb->next;
int rc;
Expand Down
5 changes: 3 additions & 2 deletions trunk/net/core/skbuff.c
Original file line number Diff line number Diff line change
Expand Up @@ -1848,13 +1848,13 @@ EXPORT_SYMBOL_GPL(skb_pull_rcsum);
/**
* skb_segment - Perform protocol segmentation on skb.
* @skb: buffer to segment
* @sg: whether scatter-gather can be used for generated segments
* @features: features for the output path (see dev->features)
*
* This function performs segmentation on the given skb. It returns
* the segment at the given position. It returns NULL if there are
* no more segments to generate, or when an error is encountered.
*/
struct sk_buff *skb_segment(struct sk_buff *skb, int sg)
struct sk_buff *skb_segment(struct sk_buff *skb, int features)
{
struct sk_buff *segs = NULL;
struct sk_buff *tail = NULL;
Expand All @@ -1863,6 +1863,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int sg)
unsigned int offset = doffset;
unsigned int headroom;
unsigned int len;
int sg = features & NETIF_F_SG;
int nfrags = skb_shinfo(skb)->nr_frags;
int err = -ENOMEM;
int i = 0;
Expand Down
6 changes: 3 additions & 3 deletions trunk/net/ipv4/af_inet.c
Original file line number Diff line number Diff line change
Expand Up @@ -1097,7 +1097,7 @@ int inet_sk_rebuild_header(struct sock *sk)

EXPORT_SYMBOL(inet_sk_rebuild_header);

static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int sg)
static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int features)
{
struct sk_buff *segs = ERR_PTR(-EINVAL);
struct iphdr *iph;
Expand Down Expand Up @@ -1126,10 +1126,10 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int sg)
rcu_read_lock();
ops = rcu_dereference(inet_protos[proto]);
if (ops && ops->gso_segment)
segs = ops->gso_segment(skb, sg);
segs = ops->gso_segment(skb, features);
rcu_read_unlock();

if (IS_ERR(segs))
if (!segs || unlikely(IS_ERR(segs)))
goto out;

skb = segs;
Expand Down
8 changes: 6 additions & 2 deletions trunk/net/ipv4/tcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -2145,7 +2145,7 @@ int compat_tcp_getsockopt(struct sock *sk, int level, int optname,
EXPORT_SYMBOL(compat_tcp_getsockopt);
#endif

struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int sg)
struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features)
{
struct sk_buff *segs = ERR_PTR(-EINVAL);
struct tcphdr *th;
Expand All @@ -2166,10 +2166,14 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int sg)
if (!pskb_may_pull(skb, thlen))
goto out;

segs = NULL;
if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST))
goto out;

oldlen = (u16)~skb->len;
__skb_pull(skb, thlen);

segs = skb_segment(skb, sg);
segs = skb_segment(skb, features);
if (IS_ERR(segs))
goto out;

Expand Down

0 comments on commit 939a67a

Please sign in to comment.