|
|
@@ -409,6 +409,9 @@ static void __packet_set_status(struct packet_sock *po, void *frame, int status)
|
|
|
flush_dcache_page(pgv_to_page(&h.h2->tp_status));
|
|
|
break;
|
|
|
case TPACKET_V3:
|
|
|
+ h.h3->tp_status = status;
|
|
|
+ flush_dcache_page(pgv_to_page(&h.h3->tp_status));
|
|
|
+ break;
|
|
|
default:
|
|
|
WARN(1, "TPACKET version not supported.\n");
|
|
|
BUG();
|
|
|
@@ -432,6 +435,8 @@ static int __packet_get_status(struct packet_sock *po, void *frame)
|
|
|
flush_dcache_page(pgv_to_page(&h.h2->tp_status));
|
|
|
return h.h2->tp_status;
|
|
|
case TPACKET_V3:
|
|
|
+ flush_dcache_page(pgv_to_page(&h.h3->tp_status));
|
|
|
+ return h.h3->tp_status;
|
|
|
default:
|
|
|
WARN(1, "TPACKET version not supported.\n");
|
|
|
BUG();
|
|
|
@@ -2497,6 +2502,13 @@ static int tpacket_parse_header(struct packet_sock *po, void *frame,
|
|
|
ph.raw = frame;
|
|
|
|
|
|
switch (po->tp_version) {
|
|
|
+ case TPACKET_V3:
|
|
|
+ if (ph.h3->tp_next_offset != 0) {
|
|
|
+ pr_warn_once("variable sized slot not supported");
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+ tp_len = ph.h3->tp_len;
|
|
|
+ break;
|
|
|
case TPACKET_V2:
|
|
|
tp_len = ph.h2->tp_len;
|
|
|
break;
|
|
|
@@ -2516,6 +2528,9 @@ static int tpacket_parse_header(struct packet_sock *po, void *frame,
|
|
|
off_max = po->tx_ring.frame_size - tp_len;
|
|
|
if (po->sk.sk_type == SOCK_DGRAM) {
|
|
|
switch (po->tp_version) {
|
|
|
+ case TPACKET_V3:
|
|
|
+ off = ph.h3->tp_net;
|
|
|
+ break;
|
|
|
case TPACKET_V2:
|
|
|
off = ph.h2->tp_net;
|
|
|
break;
|
|
|
@@ -2525,6 +2540,9 @@ static int tpacket_parse_header(struct packet_sock *po, void *frame,
|
|
|
}
|
|
|
} else {
|
|
|
switch (po->tp_version) {
|
|
|
+ case TPACKET_V3:
|
|
|
+ off = ph.h3->tp_mac;
|
|
|
+ break;
|
|
|
case TPACKET_V2:
|
|
|
off = ph.h2->tp_mac;
|
|
|
break;
|
|
|
@@ -4113,11 +4131,6 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
|
|
|
struct tpacket_req *req = &req_u->req;
|
|
|
|
|
|
lock_sock(sk);
|
|
|
- /* Opening a Tx-ring is NOT supported in TPACKET_V3 */
|
|
|
- if (!closing && tx_ring && (po->tp_version > TPACKET_V2)) {
|
|
|
- net_warn_ratelimited("Tx-ring is not supported.\n");
|
|
|
- goto out;
|
|
|
- }
|
|
|
|
|
|
rb = tx_ring ? &po->tx_ring : &po->rx_ring;
|
|
|
rb_queue = tx_ring ? &sk->sk_write_queue : &sk->sk_receive_queue;
|
|
|
@@ -4177,11 +4190,19 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
|
|
|
goto out;
|
|
|
switch (po->tp_version) {
|
|
|
case TPACKET_V3:
|
|
|
- /* Transmit path is not supported. We checked
|
|
|
- * it above but just being paranoid
|
|
|
- */
|
|
|
- if (!tx_ring)
|
|
|
+ /* Block transmit is not supported yet */
|
|
|
+ if (!tx_ring) {
|
|
|
init_prb_bdqc(po, rb, pg_vec, req_u);
|
|
|
+ } else {
|
|
|
+ struct tpacket_req3 *req3 = &req_u->req3;
|
|
|
+
|
|
|
+ if (req3->tp_retire_blk_tov ||
|
|
|
+ req3->tp_sizeof_priv ||
|
|
|
+ req3->tp_feature_req_word) {
|
|
|
+ err = -EINVAL;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+ }
|
|
|
break;
|
|
|
default:
|
|
|
break;
|