Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 232831
b: refs/heads/master
c: e0ce4af
h: refs/heads/master
i:
  232829: 09c59b4
  232827: aa65a6c
  232823: ca27538
  232815: 7ae5e50
  232799: 0364d83
  232767: 4cea682
  232703: 6dae695
v: v3
  • Loading branch information
Ian Campbell authored and David S. Miller committed Jan 27, 2011
1 parent f3180fb commit bfcff1b
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 9 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: 389f2a18c6a2a5531ac5a155c3ba25784065b1cb
refs/heads/master: e0ce4af920eb028f38bfd680b1d733f4c7a0b7cf
96 changes: 88 additions & 8 deletions trunk/drivers/net/xen-netfront.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,9 @@ struct netfront_info {
unsigned long rx_pfn_array[NET_RX_RING_SIZE];
struct multicall_entry rx_mcl[NET_RX_RING_SIZE+1];
struct mmu_update rx_mmu[NET_RX_RING_SIZE];

/* Statistics */
int rx_gso_checksum_fixup;
};

struct netfront_rx_info {
Expand Down Expand Up @@ -770,11 +773,29 @@ static RING_IDX xennet_fill_frags(struct netfront_info *np,
return cons;
}

static int skb_checksum_setup(struct sk_buff *skb)
static int checksum_setup(struct net_device *dev, struct sk_buff *skb)
{
struct iphdr *iph;
unsigned char *th;
int err = -EPROTO;
int recalculate_partial_csum = 0;

/*
* A GSO SKB must be CHECKSUM_PARTIAL. However some buggy
* peers can fail to set NETRXF_csum_blank when sending a GSO
* frame. In this case force the SKB to CHECKSUM_PARTIAL and
* recalculate the partial checksum.
*/
if (skb->ip_summed != CHECKSUM_PARTIAL && skb_is_gso(skb)) {
struct netfront_info *np = netdev_priv(dev);
np->rx_gso_checksum_fixup++;
skb->ip_summed = CHECKSUM_PARTIAL;
recalculate_partial_csum = 1;
}

/* A non-CHECKSUM_PARTIAL SKB does not require setup. */
if (skb->ip_summed != CHECKSUM_PARTIAL)
return 0;

if (skb->protocol != htons(ETH_P_IP))
goto out;
Expand All @@ -788,9 +809,23 @@ static int skb_checksum_setup(struct sk_buff *skb)
switch (iph->protocol) {
case IPPROTO_TCP:
skb->csum_offset = offsetof(struct tcphdr, check);

if (recalculate_partial_csum) {
struct tcphdr *tcph = (struct tcphdr *)th;
tcph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
skb->len - iph->ihl*4,
IPPROTO_TCP, 0);
}
break;
case IPPROTO_UDP:
skb->csum_offset = offsetof(struct udphdr, check);

if (recalculate_partial_csum) {
struct udphdr *udph = (struct udphdr *)th;
udph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
skb->len - iph->ihl*4,
IPPROTO_UDP, 0);
}
break;
default:
if (net_ratelimit())
Expand Down Expand Up @@ -829,13 +864,11 @@ static int handle_incoming_queue(struct net_device *dev,
/* Ethernet work: Delayed to here as it peeks the header. */
skb->protocol = eth_type_trans(skb, dev);

if (skb->ip_summed == CHECKSUM_PARTIAL) {
if (skb_checksum_setup(skb)) {
kfree_skb(skb);
packets_dropped++;
dev->stats.rx_errors++;
continue;
}
if (checksum_setup(dev, skb)) {
kfree_skb(skb);
packets_dropped++;
dev->stats.rx_errors++;
continue;
}

dev->stats.rx_packets++;
Expand Down Expand Up @@ -1632,12 +1665,59 @@ static void netback_changed(struct xenbus_device *dev,
}
}

static const struct xennet_stat {
char name[ETH_GSTRING_LEN];
u16 offset;
} xennet_stats[] = {
{
"rx_gso_checksum_fixup",
offsetof(struct netfront_info, rx_gso_checksum_fixup)
},
};

static int xennet_get_sset_count(struct net_device *dev, int string_set)
{
switch (string_set) {
case ETH_SS_STATS:
return ARRAY_SIZE(xennet_stats);
default:
return -EINVAL;
}
}

static void xennet_get_ethtool_stats(struct net_device *dev,
struct ethtool_stats *stats, u64 * data)
{
void *np = netdev_priv(dev);
int i;

for (i = 0; i < ARRAY_SIZE(xennet_stats); i++)
data[i] = *(int *)(np + xennet_stats[i].offset);
}

static void xennet_get_strings(struct net_device *dev, u32 stringset, u8 * data)
{
int i;

switch (stringset) {
case ETH_SS_STATS:
for (i = 0; i < ARRAY_SIZE(xennet_stats); i++)
memcpy(data + i * ETH_GSTRING_LEN,
xennet_stats[i].name, ETH_GSTRING_LEN);
break;
}
}

static const struct ethtool_ops xennet_ethtool_ops =
{
.set_tx_csum = ethtool_op_set_tx_csum,
.set_sg = xennet_set_sg,
.set_tso = xennet_set_tso,
.get_link = ethtool_op_get_link,

.get_sset_count = xennet_get_sset_count,
.get_ethtool_stats = xennet_get_ethtool_stats,
.get_strings = xennet_get_strings,
};

#ifdef CONFIG_SYSFS
Expand Down

0 comments on commit bfcff1b

Please sign in to comment.