diff options
author | David S. Miller <davem@davemloft.net> | 2016-03-13 22:08:01 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-03-13 22:08:01 -0400 |
commit | 3c4ef85155acc8d7033d668536011f92c95f1065 (patch) | |
tree | d28919993d3d10c78120e7caa77fa21a923f20b9 | |
parent | 136ba622de49a6bf1f6e5eab3391ed5d5dbe30e3 (diff) | |
parent | 8e4ee59c1e75b74966476dcc3552c3b30d2768e7 (diff) |
Merge branch 'xen-netback-fix-multiple-extra-info-handling'
Paul Durrant says:
====================
xen-netback: fix multiple extra info handling
If a frontend passes multiple extra info fragments to netback on the guest
transmit side, because xen-netback does not account for this properly, only
a single ack response will be sent. This will eventually cause processing
of the shared ring to wedge.
This series re-imports the canonical netif.h from Xen, where the ring
protocol documentation has been updated, fixes this issue in xen-netback
and also adds a patch to reduce log spam.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/xen-netback/common.h | 1 | ||||
-rw-r--r-- | drivers/net/xen-netback/netback.c | 65 | ||||
-rw-r--r-- | drivers/net/xen-netback/xenbus.c | 2 | ||||
-rw-r--r-- | include/xen/interface/io/netif.h | 861 |
4 files changed, 809 insertions, 120 deletions
diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h index 112825200d41..f44b38846420 100644 --- a/drivers/net/xen-netback/common.h +++ b/drivers/net/xen-netback/common.h | |||
@@ -52,6 +52,7 @@ typedef unsigned int pending_ring_idx_t; | |||
52 | 52 | ||
53 | struct pending_tx_info { | 53 | struct pending_tx_info { |
54 | struct xen_netif_tx_request req; /* tx request */ | 54 | struct xen_netif_tx_request req; /* tx request */ |
55 | unsigned int extra_count; | ||
55 | /* Callback data for released SKBs. The callback is always | 56 | /* Callback data for released SKBs. The callback is always |
56 | * xenvif_zerocopy_callback, desc contains the pending_idx, which is | 57 | * xenvif_zerocopy_callback, desc contains the pending_idx, which is |
57 | * also an index in pending_tx_info array. It is initialized in | 58 | * also an index in pending_tx_info array. It is initialized in |
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index 61b97c34bb3b..b42f26029225 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c | |||
@@ -95,6 +95,7 @@ static void xenvif_idx_release(struct xenvif_queue *queue, u16 pending_idx, | |||
95 | 95 | ||
96 | static void make_tx_response(struct xenvif_queue *queue, | 96 | static void make_tx_response(struct xenvif_queue *queue, |
97 | struct xen_netif_tx_request *txp, | 97 | struct xen_netif_tx_request *txp, |
98 | unsigned int extra_count, | ||
98 | s8 st); | 99 | s8 st); |
99 | static void push_tx_responses(struct xenvif_queue *queue); | 100 | static void push_tx_responses(struct xenvif_queue *queue); |
100 | 101 | ||
@@ -696,14 +697,15 @@ void xenvif_tx_credit_callback(unsigned long data) | |||
696 | } | 697 | } |
697 | 698 | ||
698 | static void xenvif_tx_err(struct xenvif_queue *queue, | 699 | static void xenvif_tx_err(struct xenvif_queue *queue, |
699 | struct xen_netif_tx_request *txp, RING_IDX end) | 700 | struct xen_netif_tx_request *txp, |
701 | unsigned int extra_count, RING_IDX end) | ||
700 | { | 702 | { |
701 | RING_IDX cons = queue->tx.req_cons; | 703 | RING_IDX cons = queue->tx.req_cons; |
702 | unsigned long flags; | 704 | unsigned long flags; |
703 | 705 | ||
704 | do { | 706 | do { |
705 | spin_lock_irqsave(&queue->response_lock, flags); | 707 | spin_lock_irqsave(&queue->response_lock, flags); |
706 | make_tx_response(queue, txp, XEN_NETIF_RSP_ERROR); | 708 | make_tx_response(queue, txp, extra_count, XEN_NETIF_RSP_ERROR); |
707 | push_tx_responses(queue); | 709 | push_tx_responses(queue); |
708 | spin_unlock_irqrestore(&queue->response_lock, flags); | 710 | spin_unlock_irqrestore(&queue->response_lock, flags); |
709 | if (cons == end) | 711 | if (cons == end) |
@@ -724,6 +726,7 @@ static void xenvif_fatal_tx_err(struct xenvif *vif) | |||
724 | 726 | ||
725 | static int xenvif_count_requests(struct xenvif_queue *queue, | 727 | static int xenvif_count_requests(struct xenvif_queue *queue, |
726 | struct xen_netif_tx_request *first, | 728 | struct xen_netif_tx_request *first, |
729 | unsigned int extra_count, | ||
727 | struct xen_netif_tx_request *txp, | 730 | struct xen_netif_tx_request *txp, |
728 | int work_to_do) | 731 | int work_to_do) |
729 | { | 732 | { |
@@ -812,7 +815,7 @@ static int xenvif_count_requests(struct xenvif_queue *queue, | |||
812 | } while (more_data); | 815 | } while (more_data); |
813 | 816 | ||
814 | if (drop_err) { | 817 | if (drop_err) { |
815 | xenvif_tx_err(queue, first, cons + slots); | 818 | xenvif_tx_err(queue, first, extra_count, cons + slots); |
816 | return drop_err; | 819 | return drop_err; |
817 | } | 820 | } |
818 | 821 | ||
@@ -827,9 +830,10 @@ struct xenvif_tx_cb { | |||
827 | #define XENVIF_TX_CB(skb) ((struct xenvif_tx_cb *)(skb)->cb) | 830 | #define XENVIF_TX_CB(skb) ((struct xenvif_tx_cb *)(skb)->cb) |
828 | 831 | ||
829 | static inline void xenvif_tx_create_map_op(struct xenvif_queue *queue, | 832 | static inline void xenvif_tx_create_map_op(struct xenvif_queue *queue, |
830 | u16 pending_idx, | 833 | u16 pending_idx, |
831 | struct xen_netif_tx_request *txp, | 834 | struct xen_netif_tx_request *txp, |
832 | struct gnttab_map_grant_ref *mop) | 835 | unsigned int extra_count, |
836 | struct gnttab_map_grant_ref *mop) | ||
833 | { | 837 | { |
834 | queue->pages_to_map[mop-queue->tx_map_ops] = queue->mmap_pages[pending_idx]; | 838 | queue->pages_to_map[mop-queue->tx_map_ops] = queue->mmap_pages[pending_idx]; |
835 | gnttab_set_map_op(mop, idx_to_kaddr(queue, pending_idx), | 839 | gnttab_set_map_op(mop, idx_to_kaddr(queue, pending_idx), |
@@ -838,6 +842,7 @@ static inline void xenvif_tx_create_map_op(struct xenvif_queue *queue, | |||
838 | 842 | ||
839 | memcpy(&queue->pending_tx_info[pending_idx].req, txp, | 843 | memcpy(&queue->pending_tx_info[pending_idx].req, txp, |
840 | sizeof(*txp)); | 844 | sizeof(*txp)); |
845 | queue->pending_tx_info[pending_idx].extra_count = extra_count; | ||
841 | } | 846 | } |
842 | 847 | ||
843 | static inline struct sk_buff *xenvif_alloc_skb(unsigned int size) | 848 | static inline struct sk_buff *xenvif_alloc_skb(unsigned int size) |
@@ -880,7 +885,7 @@ static struct gnttab_map_grant_ref *xenvif_get_requests(struct xenvif_queue *que | |||
880 | shinfo->nr_frags++, txp++, gop++) { | 885 | shinfo->nr_frags++, txp++, gop++) { |
881 | index = pending_index(queue->pending_cons++); | 886 | index = pending_index(queue->pending_cons++); |
882 | pending_idx = queue->pending_ring[index]; | 887 | pending_idx = queue->pending_ring[index]; |
883 | xenvif_tx_create_map_op(queue, pending_idx, txp, gop); | 888 | xenvif_tx_create_map_op(queue, pending_idx, txp, 0, gop); |
884 | frag_set_pending_idx(&frags[shinfo->nr_frags], pending_idx); | 889 | frag_set_pending_idx(&frags[shinfo->nr_frags], pending_idx); |
885 | } | 890 | } |
886 | 891 | ||
@@ -893,7 +898,8 @@ static struct gnttab_map_grant_ref *xenvif_get_requests(struct xenvif_queue *que | |||
893 | shinfo->nr_frags++, txp++, gop++) { | 898 | shinfo->nr_frags++, txp++, gop++) { |
894 | index = pending_index(queue->pending_cons++); | 899 | index = pending_index(queue->pending_cons++); |
895 | pending_idx = queue->pending_ring[index]; | 900 | pending_idx = queue->pending_ring[index]; |
896 | xenvif_tx_create_map_op(queue, pending_idx, txp, gop); | 901 | xenvif_tx_create_map_op(queue, pending_idx, txp, 0, |
902 | gop); | ||
897 | frag_set_pending_idx(&frags[shinfo->nr_frags], | 903 | frag_set_pending_idx(&frags[shinfo->nr_frags], |
898 | pending_idx); | 904 | pending_idx); |
899 | } | 905 | } |
@@ -1095,8 +1101,9 @@ static void xenvif_fill_frags(struct xenvif_queue *queue, struct sk_buff *skb) | |||
1095 | } | 1101 | } |
1096 | 1102 | ||
1097 | static int xenvif_get_extras(struct xenvif_queue *queue, | 1103 | static int xenvif_get_extras(struct xenvif_queue *queue, |
1098 | struct xen_netif_extra_info *extras, | 1104 | struct xen_netif_extra_info *extras, |
1099 | int work_to_do) | 1105 | unsigned int *extra_count, |
1106 | int work_to_do) | ||
1100 | { | 1107 | { |
1101 | struct xen_netif_extra_info extra; | 1108 | struct xen_netif_extra_info extra; |
1102 | RING_IDX cons = queue->tx.req_cons; | 1109 | RING_IDX cons = queue->tx.req_cons; |
@@ -1109,9 +1116,12 @@ static int xenvif_get_extras(struct xenvif_queue *queue, | |||
1109 | } | 1116 | } |
1110 | 1117 | ||
1111 | RING_COPY_REQUEST(&queue->tx, cons, &extra); | 1118 | RING_COPY_REQUEST(&queue->tx, cons, &extra); |
1119 | |||
1120 | queue->tx.req_cons = ++cons; | ||
1121 | (*extra_count)++; | ||
1122 | |||
1112 | if (unlikely(!extra.type || | 1123 | if (unlikely(!extra.type || |
1113 | extra.type >= XEN_NETIF_EXTRA_TYPE_MAX)) { | 1124 | extra.type >= XEN_NETIF_EXTRA_TYPE_MAX)) { |
1114 | queue->tx.req_cons = ++cons; | ||
1115 | netdev_err(queue->vif->dev, | 1125 | netdev_err(queue->vif->dev, |
1116 | "Invalid extra type: %d\n", extra.type); | 1126 | "Invalid extra type: %d\n", extra.type); |
1117 | xenvif_fatal_tx_err(queue->vif); | 1127 | xenvif_fatal_tx_err(queue->vif); |
@@ -1119,7 +1129,6 @@ static int xenvif_get_extras(struct xenvif_queue *queue, | |||
1119 | } | 1129 | } |
1120 | 1130 | ||
1121 | memcpy(&extras[extra.type - 1], &extra, sizeof(extra)); | 1131 | memcpy(&extras[extra.type - 1], &extra, sizeof(extra)); |
1122 | queue->tx.req_cons = ++cons; | ||
1123 | } while (extra.flags & XEN_NETIF_EXTRA_FLAG_MORE); | 1132 | } while (extra.flags & XEN_NETIF_EXTRA_FLAG_MORE); |
1124 | 1133 | ||
1125 | return work_to_do; | 1134 | return work_to_do; |
@@ -1294,6 +1303,7 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue, | |||
1294 | struct xen_netif_tx_request txreq; | 1303 | struct xen_netif_tx_request txreq; |
1295 | struct xen_netif_tx_request txfrags[XEN_NETBK_LEGACY_SLOTS_MAX]; | 1304 | struct xen_netif_tx_request txfrags[XEN_NETBK_LEGACY_SLOTS_MAX]; |
1296 | struct xen_netif_extra_info extras[XEN_NETIF_EXTRA_TYPE_MAX-1]; | 1305 | struct xen_netif_extra_info extras[XEN_NETIF_EXTRA_TYPE_MAX-1]; |
1306 | unsigned int extra_count; | ||
1297 | u16 pending_idx; | 1307 | u16 pending_idx; |
1298 | RING_IDX idx; | 1308 | RING_IDX idx; |
1299 | int work_to_do; | 1309 | int work_to_do; |
@@ -1330,8 +1340,10 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue, | |||
1330 | queue->tx.req_cons = ++idx; | 1340 | queue->tx.req_cons = ++idx; |
1331 | 1341 | ||
1332 | memset(extras, 0, sizeof(extras)); | 1342 | memset(extras, 0, sizeof(extras)); |
1343 | extra_count = 0; | ||
1333 | if (txreq.flags & XEN_NETTXF_extra_info) { | 1344 | if (txreq.flags & XEN_NETTXF_extra_info) { |
1334 | work_to_do = xenvif_get_extras(queue, extras, | 1345 | work_to_do = xenvif_get_extras(queue, extras, |
1346 | &extra_count, | ||
1335 | work_to_do); | 1347 | work_to_do); |
1336 | idx = queue->tx.req_cons; | 1348 | idx = queue->tx.req_cons; |
1337 | if (unlikely(work_to_do < 0)) | 1349 | if (unlikely(work_to_do < 0)) |
@@ -1344,7 +1356,7 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue, | |||
1344 | extra = &extras[XEN_NETIF_EXTRA_TYPE_MCAST_ADD - 1]; | 1356 | extra = &extras[XEN_NETIF_EXTRA_TYPE_MCAST_ADD - 1]; |
1345 | ret = xenvif_mcast_add(queue->vif, extra->u.mcast.addr); | 1357 | ret = xenvif_mcast_add(queue->vif, extra->u.mcast.addr); |
1346 | 1358 | ||
1347 | make_tx_response(queue, &txreq, | 1359 | make_tx_response(queue, &txreq, extra_count, |
1348 | (ret == 0) ? | 1360 | (ret == 0) ? |
1349 | XEN_NETIF_RSP_OKAY : | 1361 | XEN_NETIF_RSP_OKAY : |
1350 | XEN_NETIF_RSP_ERROR); | 1362 | XEN_NETIF_RSP_ERROR); |
@@ -1358,12 +1370,14 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue, | |||
1358 | extra = &extras[XEN_NETIF_EXTRA_TYPE_MCAST_DEL - 1]; | 1370 | extra = &extras[XEN_NETIF_EXTRA_TYPE_MCAST_DEL - 1]; |
1359 | xenvif_mcast_del(queue->vif, extra->u.mcast.addr); | 1371 | xenvif_mcast_del(queue->vif, extra->u.mcast.addr); |
1360 | 1372 | ||
1361 | make_tx_response(queue, &txreq, XEN_NETIF_RSP_OKAY); | 1373 | make_tx_response(queue, &txreq, extra_count, |
1374 | XEN_NETIF_RSP_OKAY); | ||
1362 | push_tx_responses(queue); | 1375 | push_tx_responses(queue); |
1363 | continue; | 1376 | continue; |
1364 | } | 1377 | } |
1365 | 1378 | ||
1366 | ret = xenvif_count_requests(queue, &txreq, txfrags, work_to_do); | 1379 | ret = xenvif_count_requests(queue, &txreq, extra_count, |
1380 | txfrags, work_to_do); | ||
1367 | if (unlikely(ret < 0)) | 1381 | if (unlikely(ret < 0)) |
1368 | break; | 1382 | break; |
1369 | 1383 | ||
@@ -1372,7 +1386,7 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue, | |||
1372 | if (unlikely(txreq.size < ETH_HLEN)) { | 1386 | if (unlikely(txreq.size < ETH_HLEN)) { |
1373 | netdev_dbg(queue->vif->dev, | 1387 | netdev_dbg(queue->vif->dev, |
1374 | "Bad packet size: %d\n", txreq.size); | 1388 | "Bad packet size: %d\n", txreq.size); |
1375 | xenvif_tx_err(queue, &txreq, idx); | 1389 | xenvif_tx_err(queue, &txreq, extra_count, idx); |
1376 | break; | 1390 | break; |
1377 | } | 1391 | } |
1378 | 1392 | ||
@@ -1397,7 +1411,7 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue, | |||
1397 | if (unlikely(skb == NULL)) { | 1411 | if (unlikely(skb == NULL)) { |
1398 | netdev_dbg(queue->vif->dev, | 1412 | netdev_dbg(queue->vif->dev, |
1399 | "Can't allocate a skb in start_xmit.\n"); | 1413 | "Can't allocate a skb in start_xmit.\n"); |
1400 | xenvif_tx_err(queue, &txreq, idx); | 1414 | xenvif_tx_err(queue, &txreq, extra_count, idx); |
1401 | break; | 1415 | break; |
1402 | } | 1416 | } |
1403 | 1417 | ||
@@ -1416,7 +1430,7 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue, | |||
1416 | nskb = xenvif_alloc_skb(0); | 1430 | nskb = xenvif_alloc_skb(0); |
1417 | if (unlikely(nskb == NULL)) { | 1431 | if (unlikely(nskb == NULL)) { |
1418 | kfree_skb(skb); | 1432 | kfree_skb(skb); |
1419 | xenvif_tx_err(queue, &txreq, idx); | 1433 | xenvif_tx_err(queue, &txreq, extra_count, idx); |
1420 | if (net_ratelimit()) | 1434 | if (net_ratelimit()) |
1421 | netdev_err(queue->vif->dev, | 1435 | netdev_err(queue->vif->dev, |
1422 | "Can't allocate the frag_list skb.\n"); | 1436 | "Can't allocate the frag_list skb.\n"); |
@@ -1457,13 +1471,16 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue, | |||
1457 | if (data_len < txreq.size) { | 1471 | if (data_len < txreq.size) { |
1458 | frag_set_pending_idx(&skb_shinfo(skb)->frags[0], | 1472 | frag_set_pending_idx(&skb_shinfo(skb)->frags[0], |
1459 | pending_idx); | 1473 | pending_idx); |
1460 | xenvif_tx_create_map_op(queue, pending_idx, &txreq, gop); | 1474 | xenvif_tx_create_map_op(queue, pending_idx, &txreq, |
1475 | extra_count, gop); | ||
1461 | gop++; | 1476 | gop++; |
1462 | } else { | 1477 | } else { |
1463 | frag_set_pending_idx(&skb_shinfo(skb)->frags[0], | 1478 | frag_set_pending_idx(&skb_shinfo(skb)->frags[0], |
1464 | INVALID_PENDING_IDX); | 1479 | INVALID_PENDING_IDX); |
1465 | memcpy(&queue->pending_tx_info[pending_idx].req, &txreq, | 1480 | memcpy(&queue->pending_tx_info[pending_idx].req, |
1466 | sizeof(txreq)); | 1481 | &txreq, sizeof(txreq)); |
1482 | queue->pending_tx_info[pending_idx].extra_count = | ||
1483 | extra_count; | ||
1467 | } | 1484 | } |
1468 | 1485 | ||
1469 | queue->pending_cons++; | 1486 | queue->pending_cons++; |
@@ -1804,7 +1821,8 @@ static void xenvif_idx_release(struct xenvif_queue *queue, u16 pending_idx, | |||
1804 | 1821 | ||
1805 | spin_lock_irqsave(&queue->response_lock, flags); | 1822 | spin_lock_irqsave(&queue->response_lock, flags); |
1806 | 1823 | ||
1807 | make_tx_response(queue, &pending_tx_info->req, status); | 1824 | make_tx_response(queue, &pending_tx_info->req, |
1825 | pending_tx_info->extra_count, status); | ||
1808 | 1826 | ||
1809 | /* Release the pending index before pusing the Tx response so | 1827 | /* Release the pending index before pusing the Tx response so |
1810 | * its available before a new Tx request is pushed by the | 1828 | * its available before a new Tx request is pushed by the |
@@ -1821,6 +1839,7 @@ static void xenvif_idx_release(struct xenvif_queue *queue, u16 pending_idx, | |||
1821 | 1839 | ||
1822 | static void make_tx_response(struct xenvif_queue *queue, | 1840 | static void make_tx_response(struct xenvif_queue *queue, |
1823 | struct xen_netif_tx_request *txp, | 1841 | struct xen_netif_tx_request *txp, |
1842 | unsigned int extra_count, | ||
1824 | s8 st) | 1843 | s8 st) |
1825 | { | 1844 | { |
1826 | RING_IDX i = queue->tx.rsp_prod_pvt; | 1845 | RING_IDX i = queue->tx.rsp_prod_pvt; |
@@ -1830,7 +1849,7 @@ static void make_tx_response(struct xenvif_queue *queue, | |||
1830 | resp->id = txp->id; | 1849 | resp->id = txp->id; |
1831 | resp->status = st; | 1850 | resp->status = st; |
1832 | 1851 | ||
1833 | if (txp->flags & XEN_NETTXF_extra_info) | 1852 | while (extra_count-- != 0) |
1834 | RING_GET_RESPONSE(&queue->tx, ++i)->status = XEN_NETIF_RSP_NULL; | 1853 | RING_GET_RESPONSE(&queue->tx, ++i)->status = XEN_NETIF_RSP_NULL; |
1835 | 1854 | ||
1836 | queue->tx.rsp_prod_pvt = ++i; | 1855 | queue->tx.rsp_prod_pvt = ++i; |
diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c index 39a303de20dd..bd182cd55dda 100644 --- a/drivers/net/xen-netback/xenbus.c +++ b/drivers/net/xen-netback/xenbus.c | |||
@@ -511,8 +511,6 @@ static void set_backend_state(struct backend_info *be, | |||
511 | switch (state) { | 511 | switch (state) { |
512 | case XenbusStateInitWait: | 512 | case XenbusStateInitWait: |
513 | case XenbusStateConnected: | 513 | case XenbusStateConnected: |
514 | pr_info("%s: prepare for reconnect\n", | ||
515 | be->dev->nodename); | ||
516 | backend_switch_state(be, XenbusStateInitWait); | 514 | backend_switch_state(be, XenbusStateInitWait); |
517 | break; | 515 | break; |
518 | case XenbusStateClosing: | 516 | case XenbusStateClosing: |
diff --git a/include/xen/interface/io/netif.h b/include/xen/interface/io/netif.h index 252ffd4801ef..4f20dbc42910 100644 --- a/include/xen/interface/io/netif.h +++ b/include/xen/interface/io/netif.h | |||
@@ -1,16 +1,34 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | * netif.h | 2 | * xen_netif.h |
3 | * | 3 | * |
4 | * Unified network-device I/O interface for Xen guest OSes. | 4 | * Unified network-device I/O interface for Xen guest OSes. |
5 | * | 5 | * |
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
7 | * of this software and associated documentation files (the "Software"), to | ||
8 | * deal in the Software without restriction, including without limitation the | ||
9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | ||
10 | * sell copies of the Software, and to permit persons to whom the Software is | ||
11 | * furnished to do so, subject to the following conditions: | ||
12 | * | ||
13 | * The above copyright notice and this permission notice shall be included in | ||
14 | * all copies or substantial portions of the Software. | ||
15 | * | ||
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
22 | * DEALINGS IN THE SOFTWARE. | ||
23 | * | ||
6 | * Copyright (c) 2003-2004, Keir Fraser | 24 | * Copyright (c) 2003-2004, Keir Fraser |
7 | */ | 25 | */ |
8 | 26 | ||
9 | #ifndef __XEN_PUBLIC_IO_NETIF_H__ | 27 | #ifndef __XEN_PUBLIC_IO_XEN_NETIF_H__ |
10 | #define __XEN_PUBLIC_IO_NETIF_H__ | 28 | #define __XEN_PUBLIC_IO_XEN_NETIF_H__ |
11 | 29 | ||
12 | #include <xen/interface/io/ring.h> | 30 | #include "ring.h" |
13 | #include <xen/interface/grant_table.h> | 31 | #include "../grant_table.h" |
14 | 32 | ||
15 | /* | 33 | /* |
16 | * Older implementation of Xen network frontend / backend has an | 34 | * Older implementation of Xen network frontend / backend has an |
@@ -38,10 +56,10 @@ | |||
38 | * that it cannot safely queue packets (as it may not be kicked to send them). | 56 | * that it cannot safely queue packets (as it may not be kicked to send them). |
39 | */ | 57 | */ |
40 | 58 | ||
41 | /* | 59 | /* |
42 | * "feature-split-event-channels" is introduced to separate guest TX | 60 | * "feature-split-event-channels" is introduced to separate guest TX |
43 | * and RX notificaion. Backend either doesn't support this feature or | 61 | * and RX notification. Backend either doesn't support this feature or |
44 | * advertise it via xenstore as 0 (disabled) or 1 (enabled). | 62 | * advertises it via xenstore as 0 (disabled) or 1 (enabled). |
45 | * | 63 | * |
46 | * To make use of this feature, frontend should allocate two event | 64 | * To make use of this feature, frontend should allocate two event |
47 | * channels for TX and RX, advertise them to backend as | 65 | * channels for TX and RX, advertise them to backend as |
@@ -118,151 +136,804 @@ | |||
118 | */ | 136 | */ |
119 | 137 | ||
120 | /* | 138 | /* |
121 | * This is the 'wire' format for packets: | 139 | * "feature-multicast-control" and "feature-dynamic-multicast-control" |
122 | * Request 1: xen_netif_tx_request -- XEN_NETTXF_* (any flags) | 140 | * advertise the capability to filter ethernet multicast packets in the |
123 | * [Request 2: xen_netif_extra_info] (only if request 1 has XEN_NETTXF_extra_info) | 141 | * backend. If the frontend wishes to take advantage of this feature then |
124 | * [Request 3: xen_netif_extra_info] (only if request 2 has XEN_NETIF_EXTRA_MORE) | 142 | * it may set "request-multicast-control". If the backend only advertises |
125 | * Request 4: xen_netif_tx_request -- XEN_NETTXF_more_data | 143 | * "feature-multicast-control" then "request-multicast-control" must be set |
126 | * Request 5: xen_netif_tx_request -- XEN_NETTXF_more_data | 144 | * before the frontend moves into the connected state. The backend will |
145 | * sample the value on this state transition and any subsequent change in | ||
146 | * value will have no effect. However, if the backend also advertises | ||
147 | * "feature-dynamic-multicast-control" then "request-multicast-control" | ||
148 | * may be set by the frontend at any time. In this case, the backend will | ||
149 | * watch the value and re-sample on watch events. | ||
150 | * | ||
151 | * If the sampled value of "request-multicast-control" is set then the | ||
152 | * backend transmit side should no longer flood multicast packets to the | ||
153 | * frontend, it should instead drop any multicast packet that does not | ||
154 | * match in a filter list. | ||
155 | * The list is amended by the frontend by sending dummy transmit requests | ||
156 | * containing XEN_NETIF_EXTRA_TYPE_MCAST_{ADD,DEL} extra-info fragments as | ||
157 | * specified below. | ||
158 | * Note that the filter list may be amended even if the sampled value of | ||
159 | * "request-multicast-control" is not set, however the filter should only | ||
160 | * be applied if it is set. | ||
161 | */ | ||
162 | |||
163 | /* | ||
164 | * Control ring | ||
165 | * ============ | ||
166 | * | ||
167 | * Some features, such as hashing (detailed below), require a | ||
168 | * significant amount of out-of-band data to be passed from frontend to | ||
169 | * backend. Use of xenstore is not suitable for large quantities of data | ||
170 | * because of quota limitations and so a dedicated 'control ring' is used. | ||
171 | * The ability of the backend to use a control ring is advertised by | ||
172 | * setting: | ||
173 | * | ||
174 | * /local/domain/X/backend/<domid>/<vif>/feature-ctrl-ring = "1" | ||
175 | * | ||
176 | * The frontend provides a control ring to the backend by setting: | ||
177 | * | ||
178 | * /local/domain/<domid>/device/vif/<vif>/ctrl-ring-ref = <gref> | ||
179 | * /local/domain/<domid>/device/vif/<vif>/event-channel-ctrl = <port> | ||
180 | * | ||
181 | * where <gref> is the grant reference of the shared page used to | ||
182 | * implement the control ring and <port> is an event channel to be used | ||
183 | * as a mailbox interrupt. These keys must be set before the frontend | ||
184 | * moves into the connected state. | ||
185 | * | ||
186 | * The control ring uses a fixed request/response message size and is | ||
187 | * balanced (i.e. one request to one response), so operationally it is much | ||
188 | * the same as a transmit or receive ring. | ||
189 | * Note that there is no requirement that responses are issued in the same | ||
190 | * order as requests. | ||
191 | */ | ||
192 | |||
193 | /* | ||
194 | * Hash types | ||
195 | * ========== | ||
196 | * | ||
197 | * For the purposes of the definitions below, 'Packet[]' is an array of | ||
198 | * octets containing an IP packet without options, 'Array[X..Y]' means a | ||
199 | * sub-array of 'Array' containing bytes X thru Y inclusive, and '+' is | ||
200 | * used to indicate concatenation of arrays. | ||
201 | */ | ||
202 | |||
203 | /* | ||
204 | * A hash calculated over an IP version 4 header as follows: | ||
205 | * | ||
206 | * Buffer[0..8] = Packet[12..15] (source address) + | ||
207 | * Packet[16..19] (destination address) | ||
208 | * | ||
209 | * Result = Hash(Buffer, 8) | ||
210 | */ | ||
211 | #define _XEN_NETIF_CTRL_HASH_TYPE_IPV4 0 | ||
212 | #define XEN_NETIF_CTRL_HASH_TYPE_IPV4 \ | ||
213 | (1 << _XEN_NETIF_CTRL_HASH_TYPE_IPV4) | ||
214 | |||
215 | /* | ||
216 | * A hash calculated over an IP version 4 header and TCP header as | ||
217 | * follows: | ||
218 | * | ||
219 | * Buffer[0..12] = Packet[12..15] (source address) + | ||
220 | * Packet[16..19] (destination address) + | ||
221 | * Packet[20..21] (source port) + | ||
222 | * Packet[22..23] (destination port) | ||
223 | * | ||
224 | * Result = Hash(Buffer, 12) | ||
225 | */ | ||
226 | #define _XEN_NETIF_CTRL_HASH_TYPE_IPV4_TCP 1 | ||
227 | #define XEN_NETIF_CTRL_HASH_TYPE_IPV4_TCP \ | ||
228 | (1 << _XEN_NETIF_CTRL_HASH_TYPE_IPV4_TCP) | ||
229 | |||
230 | /* | ||
231 | * A hash calculated over an IP version 6 header as follows: | ||
232 | * | ||
233 | * Buffer[0..32] = Packet[8..23] (source address ) + | ||
234 | * Packet[24..39] (destination address) | ||
235 | * | ||
236 | * Result = Hash(Buffer, 32) | ||
237 | */ | ||
238 | #define _XEN_NETIF_CTRL_HASH_TYPE_IPV6 2 | ||
239 | #define XEN_NETIF_CTRL_HASH_TYPE_IPV6 \ | ||
240 | (1 << _XEN_NETIF_CTRL_HASH_TYPE_IPV6) | ||
241 | |||
242 | /* | ||
243 | * A hash calculated over an IP version 6 header and TCP header as | ||
244 | * follows: | ||
245 | * | ||
246 | * Buffer[0..36] = Packet[8..23] (source address) + | ||
247 | * Packet[24..39] (destination address) + | ||
248 | * Packet[40..41] (source port) + | ||
249 | * Packet[42..43] (destination port) | ||
250 | * | ||
251 | * Result = Hash(Buffer, 36) | ||
252 | */ | ||
253 | #define _XEN_NETIF_CTRL_HASH_TYPE_IPV6_TCP 3 | ||
254 | #define XEN_NETIF_CTRL_HASH_TYPE_IPV6_TCP \ | ||
255 | (1 << _XEN_NETIF_CTRL_HASH_TYPE_IPV6_TCP) | ||
256 | |||
257 | /* | ||
258 | * Hash algorithms | ||
259 | * =============== | ||
260 | */ | ||
261 | |||
262 | #define XEN_NETIF_CTRL_HASH_ALGORITHM_NONE 0 | ||
263 | |||
264 | /* | ||
265 | * Toeplitz hash: | ||
266 | */ | ||
267 | |||
268 | #define XEN_NETIF_CTRL_HASH_ALGORITHM_TOEPLITZ 1 | ||
269 | |||
270 | /* | ||
271 | * This algorithm uses a 'key' as well as the data buffer itself. | ||
272 | * (Buffer[] and Key[] are treated as shift-registers where the MSB of | ||
273 | * Buffer/Key[0] is considered 'left-most' and the LSB of Buffer/Key[N-1] | ||
274 | * is the 'right-most'). | ||
275 | * | ||
276 | * Value = 0 | ||
277 | * For number of bits in Buffer[] | ||
278 | * If (left-most bit of Buffer[] is 1) | ||
279 | * Value ^= left-most 32 bits of Key[] | ||
280 | * Key[] << 1 | ||
281 | * Buffer[] << 1 | ||
282 | * | ||
283 | * The code below is provided for convenience where an operating system | ||
284 | * does not already provide an implementation. | ||
285 | */ | ||
286 | #ifdef XEN_NETIF_DEFINE_TOEPLITZ | ||
287 | static uint32_t xen_netif_toeplitz_hash(const uint8_t *key, | ||
288 | unsigned int keylen, | ||
289 | const uint8_t *buf, unsigned int buflen) | ||
290 | { | ||
291 | unsigned int keyi, bufi; | ||
292 | uint64_t prefix = 0; | ||
293 | uint64_t hash = 0; | ||
294 | |||
295 | /* Pre-load prefix with the first 8 bytes of the key */ | ||
296 | for (keyi = 0; keyi < 8; keyi++) { | ||
297 | prefix <<= 8; | ||
298 | prefix |= (keyi < keylen) ? key[keyi] : 0; | ||
299 | } | ||
300 | |||
301 | for (bufi = 0; bufi < buflen; bufi++) { | ||
302 | uint8_t byte = buf[bufi]; | ||
303 | unsigned int bit; | ||
304 | |||
305 | for (bit = 0; bit < 8; bit++) { | ||
306 | if (byte & 0x80) | ||
307 | hash ^= prefix; | ||
308 | prefix <<= 1; | ||
309 | byte <<= 1; | ||
310 | } | ||
311 | |||
312 | /* | ||
313 | * 'prefix' has now been left-shifted by 8, so | ||
314 | * OR in the next byte. | ||
315 | */ | ||
316 | prefix |= (keyi < keylen) ? key[keyi] : 0; | ||
317 | keyi++; | ||
318 | } | ||
319 | |||
320 | /* The valid part of the hash is in the upper 32 bits. */ | ||
321 | return hash >> 32; | ||
322 | } | ||
323 | #endif /* XEN_NETIF_DEFINE_TOEPLITZ */ | ||
324 | |||
325 | /* | ||
326 | * Control requests (struct xen_netif_ctrl_request) | ||
327 | * ================================================ | ||
328 | * | ||
329 | * All requests have the following format: | ||
330 | * | ||
331 | * 0 1 2 3 4 5 6 7 octet | ||
332 | * +-----+-----+-----+-----+-----+-----+-----+-----+ | ||
333 | * | id | type | data[0] | | ||
334 | * +-----+-----+-----+-----+-----+-----+-----+-----+ | ||
335 | * | data[1] | data[2] | | ||
336 | * +-----+-----+-----+-----+-----------------------+ | ||
337 | * | ||
338 | * id: the request identifier, echoed in response. | ||
339 | * type: the type of request (see below) | ||
340 | * data[]: any data associated with the request (determined by type) | ||
341 | */ | ||
342 | |||
343 | struct xen_netif_ctrl_request { | ||
344 | uint16_t id; | ||
345 | uint16_t type; | ||
346 | |||
347 | #define XEN_NETIF_CTRL_TYPE_INVALID 0 | ||
348 | #define XEN_NETIF_CTRL_TYPE_GET_HASH_FLAGS 1 | ||
349 | #define XEN_NETIF_CTRL_TYPE_SET_HASH_FLAGS 2 | ||
350 | #define XEN_NETIF_CTRL_TYPE_SET_HASH_KEY 3 | ||
351 | #define XEN_NETIF_CTRL_TYPE_GET_HASH_MAPPING_SIZE 4 | ||
352 | #define XEN_NETIF_CTRL_TYPE_SET_HASH_MAPPING_SIZE 5 | ||
353 | #define XEN_NETIF_CTRL_TYPE_SET_HASH_MAPPING 6 | ||
354 | #define XEN_NETIF_CTRL_TYPE_SET_HASH_ALGORITHM 7 | ||
355 | |||
356 | uint32_t data[3]; | ||
357 | }; | ||
358 | |||
359 | /* | ||
360 | * Control responses (struct xen_netif_ctrl_response) | ||
361 | * ================================================== | ||
362 | * | ||
363 | * All responses have the following format: | ||
364 | * | ||
365 | * 0 1 2 3 4 5 6 7 octet | ||
366 | * +-----+-----+-----+-----+-----+-----+-----+-----+ | ||
367 | * | id | type | status | | ||
368 | * +-----+-----+-----+-----+-----+-----+-----+-----+ | ||
369 | * | data | | ||
370 | * +-----+-----+-----+-----+ | ||
371 | * | ||
372 | * id: the corresponding request identifier | ||
373 | * type: the type of the corresponding request | ||
374 | * status: the status of request processing | ||
375 | * data: any data associated with the response (determined by type and | ||
376 | * status) | ||
377 | */ | ||
378 | |||
379 | struct xen_netif_ctrl_response { | ||
380 | uint16_t id; | ||
381 | uint16_t type; | ||
382 | uint32_t status; | ||
383 | |||
384 | #define XEN_NETIF_CTRL_STATUS_SUCCESS 0 | ||
385 | #define XEN_NETIF_CTRL_STATUS_NOT_SUPPORTED 1 | ||
386 | #define XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER 2 | ||
387 | #define XEN_NETIF_CTRL_STATUS_BUFFER_OVERFLOW 3 | ||
388 | |||
389 | uint32_t data; | ||
390 | }; | ||
391 | |||
392 | /* | ||
393 | * Control messages | ||
394 | * ================ | ||
395 | * | ||
396 | * XEN_NETIF_CTRL_TYPE_SET_HASH_ALGORITHM | ||
397 | * -------------------------------------- | ||
398 | * | ||
399 | * This is sent by the frontend to set the desired hash algorithm. | ||
400 | * | ||
401 | * Request: | ||
402 | * | ||
403 | * type = XEN_NETIF_CTRL_TYPE_SET_HASH_ALGORITHM | ||
404 | * data[0] = a XEN_NETIF_CTRL_HASH_ALGORITHM_* value | ||
405 | * data[1] = 0 | ||
406 | * data[2] = 0 | ||
407 | * | ||
408 | * Response: | ||
409 | * | ||
410 | * status = XEN_NETIF_CTRL_STATUS_NOT_SUPPORTED - Operation not | ||
411 | * supported | ||
412 | * XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER - The algorithm is not | ||
413 | * supported | ||
414 | * XEN_NETIF_CTRL_STATUS_SUCCESS - Operation successful | ||
415 | * | ||
416 | * NOTE: Setting data[0] to XEN_NETIF_CTRL_HASH_ALGORITHM_NONE disables | ||
417 | * hashing and the backend is free to choose how it steers packets | ||
418 | * to queues (which is the default behaviour). | ||
419 | * | ||
420 | * XEN_NETIF_CTRL_TYPE_GET_HASH_FLAGS | ||
421 | * ---------------------------------- | ||
422 | * | ||
423 | * This is sent by the frontend to query the types of hash supported by | ||
424 | * the backend. | ||
425 | * | ||
426 | * Request: | ||
427 | * | ||
428 | * type = XEN_NETIF_CTRL_TYPE_GET_HASH_FLAGS | ||
429 | * data[0] = 0 | ||
430 | * data[1] = 0 | ||
431 | * data[2] = 0 | ||
432 | * | ||
433 | * Response: | ||
434 | * | ||
435 | * status = XEN_NETIF_CTRL_STATUS_NOT_SUPPORTED - Operation not supported | ||
436 | * XEN_NETIF_CTRL_STATUS_SUCCESS - Operation successful | ||
437 | * data = supported hash types (if operation was successful) | ||
438 | * | ||
439 | * NOTE: A valid hash algorithm must be selected before this operation can | ||
440 | * succeed. | ||
441 | * | ||
442 | * XEN_NETIF_CTRL_TYPE_SET_HASH_FLAGS | ||
443 | * ---------------------------------- | ||
444 | * | ||
445 | * This is sent by the frontend to set the types of hash that the backend | ||
446 | * should calculate. (See above for hash type definitions). | ||
447 | * Note that the 'maximal' type of hash should always be chosen. For | ||
448 | * example, if the frontend sets both IPV4 and IPV4_TCP hash types then | ||
449 | * the latter hash type should be calculated for any TCP packet and the | ||
450 | * former only calculated for non-TCP packets. | ||
451 | * | ||
452 | * Request: | ||
453 | * | ||
454 | * type = XEN_NETIF_CTRL_TYPE_SET_HASH_FLAGS | ||
455 | * data[0] = bitwise OR of XEN_NETIF_CTRL_HASH_TYPE_* values | ||
456 | * data[1] = 0 | ||
457 | * data[2] = 0 | ||
458 | * | ||
459 | * Response: | ||
460 | * | ||
461 | * status = XEN_NETIF_CTRL_STATUS_NOT_SUPPORTED - Operation not | ||
462 | * supported | ||
463 | * XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER - One or more flag | ||
464 | * value is invalid or | ||
465 | * unsupported | ||
466 | * XEN_NETIF_CTRL_STATUS_SUCCESS - Operation successful | ||
467 | * data = 0 | ||
468 | * | ||
469 | * NOTE: A valid hash algorithm must be selected before this operation can | ||
470 | * succeed. | ||
471 | * Also, setting data[0] to zero disables hashing and the backend | ||
472 | * is free to choose how it steers packets to queues. | ||
473 | * | ||
474 | * XEN_NETIF_CTRL_TYPE_SET_HASH_KEY | ||
475 | * -------------------------------- | ||
476 | * | ||
477 | * This is sent by the frontend to set the key of the hash if the algorithm | ||
478 | * requires it. (See hash algorithms above). | ||
479 | * | ||
480 | * Request: | ||
481 | * | ||
482 | * type = XEN_NETIF_CTRL_TYPE_SET_HASH_KEY | ||
483 | * data[0] = grant reference of page containing the key (assumed to | ||
484 | * start at beginning of grant) | ||
485 | * data[1] = size of key in octets | ||
486 | * data[2] = 0 | ||
487 | * | ||
488 | * Response: | ||
489 | * | ||
490 | * status = XEN_NETIF_CTRL_STATUS_NOT_SUPPORTED - Operation not | ||
491 | * supported | ||
492 | * XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER - Key size is invalid | ||
493 | * XEN_NETIF_CTRL_STATUS_BUFFER_OVERFLOW - Key size is larger | ||
494 | * than the backend | ||
495 | * supports | ||
496 | * XEN_NETIF_CTRL_STATUS_SUCCESS - Operation successful | ||
497 | * data = 0 | ||
498 | * | ||
499 | * NOTE: Any key octets not specified are assumed to be zero (the key | ||
500 | * is assumed to be empty by default) and specifying a new key | ||
501 | * invalidates any previous key, hence specifying a key size of | ||
502 | * zero will clear the key (which ensures that the calculated hash | ||
503 | * will always be zero). | ||
504 | * The maximum size of key is algorithm and backend specific, but | ||
505 | * is also limited by the single grant reference. | ||
506 | * The grant reference may be read-only and must remain valid until | ||
507 | * the response has been processed. | ||
508 | * | ||
509 | * XEN_NETIF_CTRL_TYPE_GET_HASH_MAPPING_SIZE | ||
510 | * ----------------------------------------- | ||
511 | * | ||
512 | * This is sent by the frontend to query the maximum size of mapping | ||
513 | * table supported by the backend. The size is specified in terms of | ||
514 | * table entries. | ||
515 | * | ||
516 | * Request: | ||
517 | * | ||
518 | * type = XEN_NETIF_CTRL_TYPE_GET_HASH_MAPPING_SIZE | ||
519 | * data[0] = 0 | ||
520 | * data[1] = 0 | ||
521 | * data[2] = 0 | ||
522 | * | ||
523 | * Response: | ||
524 | * | ||
525 | * status = XEN_NETIF_CTRL_STATUS_NOT_SUPPORTED - Operation not supported | ||
526 | * XEN_NETIF_CTRL_STATUS_SUCCESS - Operation successful | ||
527 | * data = maximum number of entries allowed in the mapping table | ||
528 | * (if operation was successful) or zero if a mapping table is | ||
529 | * not supported (i.e. hash mapping is done only by modular | ||
530 | * arithmetic). | ||
531 | * | ||
532 | * XEN_NETIF_CTRL_TYPE_SET_HASH_MAPPING_SIZE | ||
533 | * ------------------------------------- | ||
534 | * | ||
535 | * This is sent by the frontend to set the actual size of the mapping | ||
536 | * table to be used by the backend. The size is specified in terms of | ||
537 | * table entries. | ||
538 | * Any previous table is invalidated by this message and any new table | ||
539 | * is assumed to be zero filled. | ||
540 | * | ||
541 | * Request: | ||
542 | * | ||
543 | * type = XEN_NETIF_CTRL_TYPE_SET_HASH_MAPPING_SIZE | ||
544 | * data[0] = number of entries in mapping table | ||
545 | * data[1] = 0 | ||
546 | * data[2] = 0 | ||
547 | * | ||
548 | * Response: | ||
549 | * | ||
550 | * status = XEN_NETIF_CTRL_STATUS_NOT_SUPPORTED - Operation not | ||
551 | * supported | ||
552 | * XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER - Table size is invalid | ||
553 | * XEN_NETIF_CTRL_STATUS_SUCCESS - Operation successful | ||
554 | * data = 0 | ||
555 | * | ||
556 | * NOTE: Setting data[0] to 0 means that hash mapping should be done | ||
557 | * using modular arithmetic. | ||
558 | * | ||
559 | * XEN_NETIF_CTRL_TYPE_SET_HASH_MAPPING | ||
560 | * ------------------------------------ | ||
561 | * | ||
562 | * This is sent by the frontend to set the content of the table mapping | ||
563 | * hash value to queue number. The backend should calculate the hash from | ||
564 | * the packet header, use it as an index into the table (modulo the size | ||
565 | * of the table) and then steer the packet to the queue number found at | ||
566 | * that index. | ||
567 | * | ||
568 | * Request: | ||
569 | * | ||
570 | * type = XEN_NETIF_CTRL_TYPE_SET_HASH_MAPPING | ||
571 | * data[0] = grant reference of page containing the mapping (sub-)table | ||
572 | * (assumed to start at beginning of grant) | ||
573 | * data[1] = size of (sub-)table in entries | ||
574 | * data[2] = offset, in entries, of sub-table within overall table | ||
575 | * | ||
576 | * Response: | ||
577 | * | ||
578 | * status = XEN_NETIF_CTRL_STATUS_NOT_SUPPORTED - Operation not | ||
579 | * supported | ||
580 | * XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER - Table size or content | ||
581 | * is invalid | ||
582 | * XEN_NETIF_CTRL_STATUS_BUFFER_OVERFLOW - Table size is larger | ||
583 | * than the backend | ||
584 | * supports | ||
585 | * XEN_NETIF_CTRL_STATUS_SUCCESS - Operation successful | ||
586 | * data = 0 | ||
587 | * | ||
588 | * NOTE: The overall table has the following format: | ||
589 | * | ||
590 | * 0 1 2 3 4 5 6 7 octet | ||
591 | * +-----+-----+-----+-----+-----+-----+-----+-----+ | ||
592 | * | mapping[0] | mapping[1] | | ||
593 | * +-----+-----+-----+-----+-----+-----+-----+-----+ | ||
594 | * | . | | ||
595 | * | . | | ||
596 | * | . | | ||
597 | * +-----+-----+-----+-----+-----+-----+-----+-----+ | ||
598 | * | mapping[N-2] | mapping[N-1] | | ||
599 | * +-----+-----+-----+-----+-----+-----+-----+-----+ | ||
600 | * | ||
601 | * where N is specified by a XEN_NETIF_CTRL_TYPE_SET_HASH_MAPPING_SIZE | ||
602 | * message and each mapping must specifies a queue between 0 and | ||
603 | * "multi-queue-num-queues" (see above). | ||
604 | * The backend may support a mapping table larger than can be | ||
605 | * mapped by a single grant reference. Thus sub-tables within a | ||
606 | * larger table can be individually set by sending multiple messages | ||
607 | * with differing offset values. Specifying a new sub-table does not | ||
608 | * invalidate any table data outside that range. | ||
609 | * The grant reference may be read-only and must remain valid until | ||
610 | * the response has been processed. | ||
611 | */ | ||
612 | |||
613 | DEFINE_RING_TYPES(xen_netif_ctrl, | ||
614 | struct xen_netif_ctrl_request, | ||
615 | struct xen_netif_ctrl_response); | ||
616 | |||
617 | /* | ||
618 | * Guest transmit | ||
619 | * ============== | ||
620 | * | ||
621 | * This is the 'wire' format for transmit (frontend -> backend) packets: | ||
622 | * | ||
623 | * Fragment 1: xen_netif_tx_request_t - flags = XEN_NETTXF_* | ||
624 | * size = total packet size | ||
625 | * [Extra 1: xen_netif_extra_info_t] - (only if fragment 1 flags include | ||
626 | * XEN_NETTXF_extra_info) | ||
627 | * ... | ||
628 | * [Extra N: xen_netif_extra_info_t] - (only if extra N-1 flags include | ||
629 | * XEN_NETIF_EXTRA_MORE) | ||
127 | * ... | 630 | * ... |
128 | * Request N: xen_netif_tx_request -- 0 | 631 | * Fragment N: xen_netif_tx_request_t - (only if fragment N-1 flags include |
632 | * XEN_NETTXF_more_data - flags on preceding | ||
633 | * extras are not relevant here) | ||
634 | * flags = 0 | ||
635 | * size = fragment size | ||
636 | * | ||
637 | * NOTE: | ||
638 | * | ||
639 | * This format slightly is different from that used for receive | ||
640 | * (backend -> frontend) packets. Specifically, in a multi-fragment | ||
641 | * packet the actual size of fragment 1 can only be determined by | ||
642 | * subtracting the sizes of fragments 2..N from the total packet size. | ||
643 | * | ||
644 | * Ring slot size is 12 octets, however not all request/response | ||
645 | * structs use the full size. | ||
646 | * | ||
647 | * tx request data (xen_netif_tx_request_t) | ||
648 | * ------------------------------------ | ||
649 | * | ||
650 | * 0 1 2 3 4 5 6 7 octet | ||
651 | * +-----+-----+-----+-----+-----+-----+-----+-----+ | ||
652 | * | grant ref | offset | flags | | ||
653 | * +-----+-----+-----+-----+-----+-----+-----+-----+ | ||
654 | * | id | size | | ||
655 | * +-----+-----+-----+-----+ | ||
656 | * | ||
657 | * grant ref: Reference to buffer page. | ||
658 | * offset: Offset within buffer page. | ||
659 | * flags: XEN_NETTXF_*. | ||
660 | * id: request identifier, echoed in response. | ||
661 | * size: packet size in bytes. | ||
662 | * | ||
663 | * tx response (xen_netif_tx_response_t) | ||
664 | * --------------------------------- | ||
665 | * | ||
666 | * 0 1 2 3 4 5 6 7 octet | ||
667 | * +-----+-----+-----+-----+-----+-----+-----+-----+ | ||
668 | * | id | status | unused | | ||
669 | * +-----+-----+-----+-----+-----+-----+-----+-----+ | ||
670 | * | unused | | ||
671 | * +-----+-----+-----+-----+ | ||
672 | * | ||
673 | * id: reflects id in transmit request | ||
674 | * status: XEN_NETIF_RSP_* | ||
675 | * | ||
676 | * Guest receive | ||
677 | * ============= | ||
678 | * | ||
679 | * This is the 'wire' format for receive (backend -> frontend) packets: | ||
680 | * | ||
681 | * Fragment 1: xen_netif_rx_request_t - flags = XEN_NETRXF_* | ||
682 | * size = fragment size | ||
683 | * [Extra 1: xen_netif_extra_info_t] - (only if fragment 1 flags include | ||
684 | * XEN_NETRXF_extra_info) | ||
685 | * ... | ||
686 | * [Extra N: xen_netif_extra_info_t] - (only if extra N-1 flags include | ||
687 | * XEN_NETIF_EXTRA_MORE) | ||
688 | * ... | ||
689 | * Fragment N: xen_netif_rx_request_t - (only if fragment N-1 flags include | ||
690 | * XEN_NETRXF_more_data - flags on preceding | ||
691 | * extras are not relevant here) | ||
692 | * flags = 0 | ||
693 | * size = fragment size | ||
694 | * | ||
695 | * NOTE: | ||
696 | * | ||
697 | * This format slightly is different from that used for transmit | ||
698 | * (frontend -> backend) packets. Specifically, in a multi-fragment | ||
699 | * packet the size of the packet can only be determined by summing the | ||
700 | * sizes of fragments 1..N. | ||
701 | * | ||
702 | * Ring slot size is 8 octets. | ||
703 | * | ||
704 | * rx request (xen_netif_rx_request_t) | ||
705 | * ------------------------------- | ||
706 | * | ||
707 | * 0 1 2 3 4 5 6 7 octet | ||
708 | * +-----+-----+-----+-----+-----+-----+-----+-----+ | ||
709 | * | id | pad | gref | | ||
710 | * +-----+-----+-----+-----+-----+-----+-----+-----+ | ||
711 | * | ||
712 | * id: request identifier, echoed in response. | ||
713 | * gref: reference to incoming granted frame. | ||
714 | * | ||
715 | * rx response (xen_netif_rx_response_t) | ||
716 | * --------------------------------- | ||
717 | * | ||
718 | * 0 1 2 3 4 5 6 7 octet | ||
719 | * +-----+-----+-----+-----+-----+-----+-----+-----+ | ||
720 | * | id | offset | flags | status | | ||
721 | * +-----+-----+-----+-----+-----+-----+-----+-----+ | ||
722 | * | ||
723 | * id: reflects id in receive request | ||
724 | * offset: offset in page of start of received packet | ||
725 | * flags: XEN_NETRXF_* | ||
726 | * status: -ve: XEN_NETIF_RSP_*; +ve: Rx'ed pkt size. | ||
727 | * | ||
728 | * NOTE: Historically, to support GSO on the frontend receive side, Linux | ||
729 | * netfront does not make use of the rx response id (because, as | ||
730 | * described below, extra info structures overlay the id field). | ||
731 | * Instead it assumes that responses always appear in the same ring | ||
732 | * slot as their corresponding request. Thus, to maintain | ||
733 | * compatibility, backends must make sure this is the case. | ||
734 | * | ||
735 | * Extra Info | ||
736 | * ========== | ||
737 | * | ||
738 | * Can be present if initial request or response has NET{T,R}XF_extra_info, | ||
739 | * or previous extra request has XEN_NETIF_EXTRA_MORE. | ||
740 | * | ||
741 | * The struct therefore needs to fit into either a tx or rx slot and | ||
742 | * is therefore limited to 8 octets. | ||
743 | * | ||
744 | * NOTE: Because extra info data overlays the usual request/response | ||
745 | * structures, there is no id information in the opposite direction. | ||
746 | * So, if an extra info overlays an rx response the frontend can | ||
747 | * assume that it is in the same ring slot as the request that was | ||
748 | * consumed to make the slot available, and the backend must ensure | ||
749 | * this assumption is true. | ||
750 | * | ||
751 | * extra info (xen_netif_extra_info_t) | ||
752 | * ------------------------------- | ||
753 | * | ||
754 | * General format: | ||
755 | * | ||
756 | * 0 1 2 3 4 5 6 7 octet | ||
757 | * +-----+-----+-----+-----+-----+-----+-----+-----+ | ||
758 | * |type |flags| type specific data | | ||
759 | * +-----+-----+-----+-----+-----+-----+-----+-----+ | ||
760 | * | padding for tx | | ||
761 | * +-----+-----+-----+-----+ | ||
762 | * | ||
763 | * type: XEN_NETIF_EXTRA_TYPE_* | ||
764 | * flags: XEN_NETIF_EXTRA_FLAG_* | ||
765 | * padding for tx: present only in the tx case due to 8 octet limit | ||
766 | * from rx case. Not shown in type specific entries | ||
767 | * below. | ||
768 | * | ||
769 | * XEN_NETIF_EXTRA_TYPE_GSO: | ||
770 | * | ||
771 | * 0 1 2 3 4 5 6 7 octet | ||
772 | * +-----+-----+-----+-----+-----+-----+-----+-----+ | ||
773 | * |type |flags| size |type | pad | features | | ||
774 | * +-----+-----+-----+-----+-----+-----+-----+-----+ | ||
775 | * | ||
776 | * type: Must be XEN_NETIF_EXTRA_TYPE_GSO | ||
777 | * flags: XEN_NETIF_EXTRA_FLAG_* | ||
778 | * size: Maximum payload size of each segment. For example, | ||
779 | * for TCP this is just the path MSS. | ||
780 | * type: XEN_NETIF_GSO_TYPE_*: This determines the protocol of | ||
781 | * the packet and any extra features required to segment the | ||
782 | * packet properly. | ||
783 | * features: EN_XEN_NETIF_GSO_FEAT_*: This specifies any extra GSO | ||
784 | * features required to process this packet, such as ECN | ||
785 | * support for TCPv4. | ||
786 | * | ||
787 | * XEN_NETIF_EXTRA_TYPE_MCAST_{ADD,DEL}: | ||
788 | * | ||
789 | * 0 1 2 3 4 5 6 7 octet | ||
790 | * +-----+-----+-----+-----+-----+-----+-----+-----+ | ||
791 | * |type |flags| addr | | ||
792 | * +-----+-----+-----+-----+-----+-----+-----+-----+ | ||
793 | * | ||
794 | * type: Must be XEN_NETIF_EXTRA_TYPE_MCAST_{ADD,DEL} | ||
795 | * flags: XEN_NETIF_EXTRA_FLAG_* | ||
796 | * addr: address to add/remove | ||
797 | * | ||
798 | * XEN_NETIF_EXTRA_TYPE_HASH: | ||
799 | * | ||
800 | * A backend that supports teoplitz hashing is assumed to accept | ||
801 | * this type of extra info in transmit packets. | ||
802 | * A frontend that enables hashing is assumed to accept | ||
803 | * this type of extra info in receive packets. | ||
804 | * | ||
805 | * 0 1 2 3 4 5 6 7 octet | ||
806 | * +-----+-----+-----+-----+-----+-----+-----+-----+ | ||
807 | * |type |flags|htype| alg |LSB ---- value ---- MSB| | ||
808 | * +-----+-----+-----+-----+-----+-----+-----+-----+ | ||
809 | * | ||
810 | * type: Must be XEN_NETIF_EXTRA_TYPE_HASH | ||
811 | * flags: XEN_NETIF_EXTRA_FLAG_* | ||
812 | * htype: Hash type (one of _XEN_NETIF_CTRL_HASH_TYPE_* - see above) | ||
813 | * alg: The algorithm used to calculate the hash (one of | ||
814 | * XEN_NETIF_CTRL_HASH_TYPE_ALGORITHM_* - see above) | ||
815 | * value: Hash value | ||
129 | */ | 816 | */ |
130 | 817 | ||
131 | /* Protocol checksum field is blank in the packet (hardware offload)? */ | 818 | /* Protocol checksum field is blank in the packet (hardware offload)? */ |
132 | #define _XEN_NETTXF_csum_blank (0) | 819 | #define _XEN_NETTXF_csum_blank (0) |
133 | #define XEN_NETTXF_csum_blank (1U<<_XEN_NETTXF_csum_blank) | 820 | #define XEN_NETTXF_csum_blank (1U<<_XEN_NETTXF_csum_blank) |
134 | 821 | ||
135 | /* Packet data has been validated against protocol checksum. */ | 822 | /* Packet data has been validated against protocol checksum. */ |
136 | #define _XEN_NETTXF_data_validated (1) | 823 | #define _XEN_NETTXF_data_validated (1) |
137 | #define XEN_NETTXF_data_validated (1U<<_XEN_NETTXF_data_validated) | 824 | #define XEN_NETTXF_data_validated (1U<<_XEN_NETTXF_data_validated) |
138 | 825 | ||
139 | /* Packet continues in the next request descriptor. */ | 826 | /* Packet continues in the next request descriptor. */ |
140 | #define _XEN_NETTXF_more_data (2) | 827 | #define _XEN_NETTXF_more_data (2) |
141 | #define XEN_NETTXF_more_data (1U<<_XEN_NETTXF_more_data) | 828 | #define XEN_NETTXF_more_data (1U<<_XEN_NETTXF_more_data) |
142 | 829 | ||
143 | /* Packet to be followed by extra descriptor(s). */ | 830 | /* Packet to be followed by extra descriptor(s). */ |
144 | #define _XEN_NETTXF_extra_info (3) | 831 | #define _XEN_NETTXF_extra_info (3) |
145 | #define XEN_NETTXF_extra_info (1U<<_XEN_NETTXF_extra_info) | 832 | #define XEN_NETTXF_extra_info (1U<<_XEN_NETTXF_extra_info) |
146 | 833 | ||
147 | #define XEN_NETIF_MAX_TX_SIZE 0xFFFF | 834 | #define XEN_NETIF_MAX_TX_SIZE 0xFFFF |
148 | struct xen_netif_tx_request { | 835 | struct xen_netif_tx_request { |
149 | grant_ref_t gref; /* Reference to buffer page */ | 836 | grant_ref_t gref; |
150 | uint16_t offset; /* Offset within buffer page */ | 837 | uint16_t offset; |
151 | uint16_t flags; /* XEN_NETTXF_* */ | 838 | uint16_t flags; |
152 | uint16_t id; /* Echoed in response message. */ | 839 | uint16_t id; |
153 | uint16_t size; /* Packet size in bytes. */ | 840 | uint16_t size; |
154 | }; | 841 | }; |
155 | 842 | ||
156 | /* Types of xen_netif_extra_info descriptors. */ | 843 | /* Types of xen_netif_extra_info descriptors. */ |
157 | #define XEN_NETIF_EXTRA_TYPE_NONE (0) /* Never used - invalid */ | 844 | #define XEN_NETIF_EXTRA_TYPE_NONE (0) /* Never used - invalid */ |
158 | #define XEN_NETIF_EXTRA_TYPE_GSO (1) /* u.gso */ | 845 | #define XEN_NETIF_EXTRA_TYPE_GSO (1) /* u.gso */ |
159 | #define XEN_NETIF_EXTRA_TYPE_MCAST_ADD (2) /* u.mcast */ | 846 | #define XEN_NETIF_EXTRA_TYPE_MCAST_ADD (2) /* u.mcast */ |
160 | #define XEN_NETIF_EXTRA_TYPE_MCAST_DEL (3) /* u.mcast */ | 847 | #define XEN_NETIF_EXTRA_TYPE_MCAST_DEL (3) /* u.mcast */ |
161 | #define XEN_NETIF_EXTRA_TYPE_MAX (4) | 848 | #define XEN_NETIF_EXTRA_TYPE_HASH (4) /* u.hash */ |
849 | #define XEN_NETIF_EXTRA_TYPE_MAX (5) | ||
162 | 850 | ||
163 | /* xen_netif_extra_info flags. */ | 851 | /* xen_netif_extra_info_t flags. */ |
164 | #define _XEN_NETIF_EXTRA_FLAG_MORE (0) | 852 | #define _XEN_NETIF_EXTRA_FLAG_MORE (0) |
165 | #define XEN_NETIF_EXTRA_FLAG_MORE (1U<<_XEN_NETIF_EXTRA_FLAG_MORE) | 853 | #define XEN_NETIF_EXTRA_FLAG_MORE (1U<<_XEN_NETIF_EXTRA_FLAG_MORE) |
166 | 854 | ||
167 | /* GSO types */ | 855 | /* GSO types */ |
168 | #define XEN_NETIF_GSO_TYPE_NONE (0) | 856 | #define XEN_NETIF_GSO_TYPE_NONE (0) |
169 | #define XEN_NETIF_GSO_TYPE_TCPV4 (1) | 857 | #define XEN_NETIF_GSO_TYPE_TCPV4 (1) |
170 | #define XEN_NETIF_GSO_TYPE_TCPV6 (2) | 858 | #define XEN_NETIF_GSO_TYPE_TCPV6 (2) |
171 | 859 | ||
172 | /* | 860 | /* |
173 | * This structure needs to fit within both netif_tx_request and | 861 | * This structure needs to fit within both xen_netif_tx_request_t and |
174 | * netif_rx_response for compatibility. | 862 | * xen_netif_rx_response_t for compatibility. |
175 | */ | 863 | */ |
176 | struct xen_netif_extra_info { | 864 | struct xen_netif_extra_info { |
177 | uint8_t type; /* XEN_NETIF_EXTRA_TYPE_* */ | 865 | uint8_t type; |
178 | uint8_t flags; /* XEN_NETIF_EXTRA_FLAG_* */ | 866 | uint8_t flags; |
179 | |||
180 | union { | 867 | union { |
181 | struct { | 868 | struct { |
182 | /* | ||
183 | * Maximum payload size of each segment. For | ||
184 | * example, for TCP this is just the path MSS. | ||
185 | */ | ||
186 | uint16_t size; | 869 | uint16_t size; |
187 | 870 | uint8_t type; | |
188 | /* | ||
189 | * GSO type. This determines the protocol of | ||
190 | * the packet and any extra features required | ||
191 | * to segment the packet properly. | ||
192 | */ | ||
193 | uint8_t type; /* XEN_NETIF_GSO_TYPE_* */ | ||
194 | |||
195 | /* Future expansion. */ | ||
196 | uint8_t pad; | 871 | uint8_t pad; |
197 | 872 | uint16_t features; | |
198 | /* | ||
199 | * GSO features. This specifies any extra GSO | ||
200 | * features required to process this packet, | ||
201 | * such as ECN support for TCPv4. | ||
202 | */ | ||
203 | uint16_t features; /* XEN_NETIF_GSO_FEAT_* */ | ||
204 | } gso; | 873 | } gso; |
205 | |||
206 | struct { | 874 | struct { |
207 | uint8_t addr[6]; /* Address to add/remove. */ | 875 | uint8_t addr[6]; |
208 | } mcast; | 876 | } mcast; |
209 | 877 | struct { | |
878 | uint8_t type; | ||
879 | uint8_t algorithm; | ||
880 | uint8_t value[4]; | ||
881 | } hash; | ||
210 | uint16_t pad[3]; | 882 | uint16_t pad[3]; |
211 | } u; | 883 | } u; |
212 | }; | 884 | }; |
213 | 885 | ||
214 | struct xen_netif_tx_response { | 886 | struct xen_netif_tx_response { |
215 | uint16_t id; | 887 | uint16_t id; |
216 | int16_t status; /* XEN_NETIF_RSP_* */ | 888 | int16_t status; |
217 | }; | 889 | }; |
218 | 890 | ||
219 | struct xen_netif_rx_request { | 891 | struct xen_netif_rx_request { |
220 | uint16_t id; /* Echoed in response message. */ | 892 | uint16_t id; /* Echoed in response message. */ |
221 | grant_ref_t gref; /* Reference to incoming granted frame */ | 893 | uint16_t pad; |
894 | grant_ref_t gref; | ||
222 | }; | 895 | }; |
223 | 896 | ||
224 | /* Packet data has been validated against protocol checksum. */ | 897 | /* Packet data has been validated against protocol checksum. */ |
225 | #define _XEN_NETRXF_data_validated (0) | 898 | #define _XEN_NETRXF_data_validated (0) |
226 | #define XEN_NETRXF_data_validated (1U<<_XEN_NETRXF_data_validated) | 899 | #define XEN_NETRXF_data_validated (1U<<_XEN_NETRXF_data_validated) |
227 | 900 | ||
228 | /* Protocol checksum field is blank in the packet (hardware offload)? */ | 901 | /* Protocol checksum field is blank in the packet (hardware offload)? */ |
229 | #define _XEN_NETRXF_csum_blank (1) | 902 | #define _XEN_NETRXF_csum_blank (1) |
230 | #define XEN_NETRXF_csum_blank (1U<<_XEN_NETRXF_csum_blank) | 903 | #define XEN_NETRXF_csum_blank (1U<<_XEN_NETRXF_csum_blank) |
231 | 904 | ||
232 | /* Packet continues in the next request descriptor. */ | 905 | /* Packet continues in the next request descriptor. */ |
233 | #define _XEN_NETRXF_more_data (2) | 906 | #define _XEN_NETRXF_more_data (2) |
234 | #define XEN_NETRXF_more_data (1U<<_XEN_NETRXF_more_data) | 907 | #define XEN_NETRXF_more_data (1U<<_XEN_NETRXF_more_data) |
235 | 908 | ||
236 | /* Packet to be followed by extra descriptor(s). */ | 909 | /* Packet to be followed by extra descriptor(s). */ |
237 | #define _XEN_NETRXF_extra_info (3) | 910 | #define _XEN_NETRXF_extra_info (3) |
238 | #define XEN_NETRXF_extra_info (1U<<_XEN_NETRXF_extra_info) | 911 | #define XEN_NETRXF_extra_info (1U<<_XEN_NETRXF_extra_info) |
239 | 912 | ||
240 | /* GSO Prefix descriptor. */ | 913 | /* Packet has GSO prefix. Deprecated but included for compatibility */ |
241 | #define _XEN_NETRXF_gso_prefix (4) | 914 | #define _XEN_NETRXF_gso_prefix (4) |
242 | #define XEN_NETRXF_gso_prefix (1U<<_XEN_NETRXF_gso_prefix) | 915 | #define XEN_NETRXF_gso_prefix (1U<<_XEN_NETRXF_gso_prefix) |
243 | 916 | ||
244 | struct xen_netif_rx_response { | 917 | struct xen_netif_rx_response { |
245 | uint16_t id; | 918 | uint16_t id; |
246 | uint16_t offset; /* Offset in page of start of received packet */ | 919 | uint16_t offset; |
247 | uint16_t flags; /* XEN_NETRXF_* */ | 920 | uint16_t flags; |
248 | int16_t status; /* -ve: BLKIF_RSP_* ; +ve: Rx'ed pkt size. */ | 921 | int16_t status; |
249 | }; | 922 | }; |
250 | 923 | ||
251 | /* | 924 | /* |
252 | * Generate netif ring structures and types. | 925 | * Generate xen_netif ring structures and types. |
253 | */ | 926 | */ |
254 | 927 | ||
255 | DEFINE_RING_TYPES(xen_netif_tx, | 928 | DEFINE_RING_TYPES(xen_netif_tx, struct xen_netif_tx_request, |
256 | struct xen_netif_tx_request, | ||
257 | struct xen_netif_tx_response); | 929 | struct xen_netif_tx_response); |
258 | DEFINE_RING_TYPES(xen_netif_rx, | 930 | DEFINE_RING_TYPES(xen_netif_rx, struct xen_netif_rx_request, |
259 | struct xen_netif_rx_request, | ||
260 | struct xen_netif_rx_response); | 931 | struct xen_netif_rx_response); |
261 | 932 | ||
262 | #define XEN_NETIF_RSP_DROPPED -2 | 933 | #define XEN_NETIF_RSP_DROPPED -2 |
263 | #define XEN_NETIF_RSP_ERROR -1 | 934 | #define XEN_NETIF_RSP_ERROR -1 |
264 | #define XEN_NETIF_RSP_OKAY 0 | 935 | #define XEN_NETIF_RSP_OKAY 0 |
265 | /* No response: used for auxiliary requests (e.g., xen_netif_extra_info). */ | 936 | /* No response: used for auxiliary requests (e.g., xen_netif_extra_info_t). */ |
266 | #define XEN_NETIF_RSP_NULL 1 | 937 | #define XEN_NETIF_RSP_NULL 1 |
267 | 938 | ||
268 | #endif | 939 | #endif |