Hi:
[NET] back: Transmit TSO packets if supported
This patch adds TSO transmission support to the backend.
Signed-off-by: Herbert Xu <herbert@xxxxxxxxxxxxxxxxxxx>
Cheers,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@xxxxxxxxxxxxxxxxxxx>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
diff -r 3df7a115ddde -r 04cbf628ed5a
linux-2.6-xen-sparse/drivers/xen/netback/interface.c
--- a/linux-2.6-xen-sparse/drivers/xen/netback/interface.c Fri Jul 28
18:22:38 2006 +1000
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/interface.c Fri Jul 28
18:24:10 2006 +1000
@@ -84,12 +84,26 @@ static int netbk_set_sg(struct net_devic
return ethtool_op_set_sg(dev, data);
}
+static int netbk_set_tso(struct net_device *dev, u32 data)
+{
+ if (data) {
+ netif_t *netif = netdev_priv(dev);
+
+ if (!(netif->features & NETIF_F_TSO))
+ return -ENOSYS;
+ }
+
+ return ethtool_op_set_tso(dev, data);
+}
+
static struct ethtool_ops network_ethtool_ops =
{
.get_tx_csum = ethtool_op_get_tx_csum,
.set_tx_csum = ethtool_op_set_tx_csum,
.get_sg = ethtool_op_get_sg,
.set_sg = netbk_set_sg,
+ .get_tso = ethtool_op_get_tso,
+ .set_tso = netbk_set_tso,
.get_link = ethtool_op_get_link,
};
diff -r 3df7a115ddde -r 04cbf628ed5a
linux-2.6-xen-sparse/drivers/xen/netback/netback.c
--- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Fri Jul 28
18:22:38 2006 +1000
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Fri Jul 28
18:24:10 2006 +1000
@@ -50,12 +50,12 @@ static void make_tx_response(netif_t *ne
static void make_tx_response(netif_t *netif,
netif_tx_request_t *txp,
s8 st);
-static int make_rx_response(netif_t *netif,
- u16 id,
- s8 st,
- u16 offset,
- u16 size,
- u16 flags);
+static netif_rx_response_t *make_rx_response(netif_t *netif,
+ u16 id,
+ s8 st,
+ u16 offset,
+ u16 size,
+ u16 flags);
static void net_tx_action(unsigned long unused);
static DECLARE_TASKLET(net_tx_tasklet, net_tx_action, 0);
@@ -225,9 +225,9 @@ static inline int netbk_queue_full(netif
{
RING_IDX peek = netif->rx_req_cons_peek;
- return netif->rx.sring->req_prod - peek <= MAX_SKB_FRAGS ||
+ return netif->rx.sring->req_prod - peek <= MAX_SKB_FRAGS + 1 ||
netif->rx.rsp_prod_pvt + NET_RX_RING_SIZE - peek <=
- MAX_SKB_FRAGS;
+ MAX_SKB_FRAGS + 1;
}
int netif_be_start_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -263,7 +263,8 @@ int netif_be_start_xmit(struct sk_buff *
skb = nskb;
}
- netif->rx_req_cons_peek += skb_shinfo(skb)->nr_frags + 1;
+ netif->rx_req_cons_peek += skb_shinfo(skb)->nr_frags + 1 +
+ !!skb_shinfo(skb)->gso_size;
netif_get(netif);
if (netbk_can_queue(dev) && netbk_queue_full(netif))
@@ -340,11 +341,16 @@ static void netbk_gop_skb(struct sk_buff
netif_t *netif = netdev_priv(skb->dev);
int nr_frags = skb_shinfo(skb)->nr_frags;
int i;
+ int extra;
+
+ meta[count].frag.page_offset = skb_shinfo(skb)->gso_type;
+ meta[count].frag.size = skb_shinfo(skb)->gso_size;
+ extra = !!meta[count].frag.size + 1;
for (i = 0; i < nr_frags; i++) {
meta[++count].frag = skb_shinfo(skb)->frags[i];
meta[count].id = netbk_gop_frag(netif, meta[count].frag.page,
- count, i + 1);
+ count, i + extra);
}
/*
@@ -354,7 +360,7 @@ static void netbk_gop_skb(struct sk_buff
meta[count - nr_frags].id = netbk_gop_frag(netif,
virt_to_page(skb->data),
count - nr_frags, 0);
- netif->rx.req_cons += nr_frags + 1;
+ netif->rx.req_cons += nr_frags + extra;
}
static inline void netbk_free_pages(int nr_frags, struct netbk_rx_meta *meta)
@@ -415,6 +421,8 @@ static void net_rx_action(unsigned long
netif_t *netif = NULL;
s8 status;
u16 id, irq, flags;
+ netif_rx_response_t *resp;
+ struct netif_extra_info *extra;
multicall_entry_t *mcl;
struct sk_buff_head rxq;
struct sk_buff *skb;
@@ -504,8 +512,33 @@ static void net_rx_action(unsigned long
else if (skb->proto_data_valid) /* remote but checksummed? */
flags |= NETRXF_data_validated;
- make_rx_response(netif, id, status, offset_in_page(skb->data),
- skb_headlen(skb), flags);
+ resp = make_rx_response(netif, id, status,
+ offset_in_page(skb->data),
+ skb_headlen(skb), flags);
+
+ extra = NULL;
+
+ if (meta[count].frag.size) {
+ struct netif_extra_info *gso =
+ (struct netif_extra_info *)
+ RING_GET_RESPONSE(&netif->rx,
+ netif->rx.rsp_prod_pvt++);
+
+ if (extra)
+ extra->flags |= XEN_NETIF_EXTRA_FLAG_MORE;
+ else
+ resp->flags |= NETRXF_extra_info;
+
+ gso->u.gso.size = meta[count].frag.size;
+ gso->u.gso.type = XEN_NETIF_GSO_TYPE_TCPV4;
+ gso->u.gso.pad = 0;
+ gso->u.gso.features = 0;
+
+ gso->type = XEN_NETIF_EXTRA_TYPE_GSO;
+ gso->flags = 0;
+ extra = gso;
+ }
+
netbk_add_frag_responses(netif, status, meta + count + 1,
nr_frags);
@@ -1183,12 +1216,12 @@ static void make_tx_response(netif_t *ne
#endif
}
-static int make_rx_response(netif_t *netif,
- u16 id,
- s8 st,
- u16 offset,
- u16 size,
- u16 flags)
+static netif_rx_response_t *make_rx_response(netif_t *netif,
+ u16 id,
+ s8 st,
+ u16 offset,
+ u16 size,
+ u16 flags)
{
RING_IDX i = netif->rx.rsp_prod_pvt;
netif_rx_response_t *resp;
@@ -1203,7 +1236,7 @@ static int make_rx_response(netif_t *net
netif->rx.rsp_prod_pvt = ++i;
- return 0;
+ return resp;
}
#ifdef NETBE_DEBUG_INTERRUPT
diff -r 3df7a115ddde -r 04cbf628ed5a
linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c
--- a/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c Fri Jul 28 18:22:38
2006 +1000
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c Fri Jul 28 18:24:10
2006 +1000
@@ -384,6 +384,14 @@ static int connect_rings(struct backend_
be->netif->dev->features |= NETIF_F_SG;
}
+ if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-gso-tcpv4", "%d",
+ &val) < 0)
+ val = 0;
+ if (val) {
+ be->netif->features |= NETIF_F_TSO;
+ be->netif->dev->features |= NETIF_F_TSO;
+ }
+
/* Map the shared frame, irq etc. */
err = netif_map(be->netif, tx_ring_ref, rx_ring_ref, evtchn);
if (err) {
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|