]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - net/packet/af_packet.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[mirror_ubuntu-artful-kernel.git] / net / packet / af_packet.c
index 70f5b6a4683c29351284e3385f56caf1bce37ac7..2bd0d1949312c3d71c4b33529316dcfe76fa28f1 100644 (file)
@@ -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();
@@ -476,6 +481,9 @@ static __u32 __packet_set_timestamp(struct packet_sock *po, void *frame,
                h.h2->tp_nsec = ts.tv_nsec;
                break;
        case TPACKET_V3:
+               h.h3->tp_sec = ts.tv_sec;
+               h.h3->tp_nsec = ts.tv_nsec;
+               break;
        default:
                WARN(1, "TPACKET version not supported.\n");
                BUG();
@@ -2510,6 +2518,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;
@@ -2529,6 +2544,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;
@@ -2538,6 +2556,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;
@@ -4132,11 +4153,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;
@@ -4196,11 +4212,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;