Phonet: zero-copy GPRS TX
Rémi Denis-Courmont [Mon, 4 Jan 2010 02:02:48 +0000 (02:02 +0000)]
Send aligned pipe payload if requested to do so. Then, the socket buffer
needs not be fragmented anymore.

Signed-off-by: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

include/net/phonet/pep.h
net/phonet/pep.c

index c371625..35672b1 100644 (file)
@@ -44,6 +44,7 @@ struct pep_sock {
        u8                      rx_fc;  /* RX flow control */
        u8                      tx_fc;  /* TX flow control */
        u8                      init_enable;    /* auto-enable at creation */
+       u8                      aligned;
 };
 
 static inline struct pep_sock *pep_sk(struct sock *sk)
@@ -139,6 +140,7 @@ enum {
        PN_PIPE_SB_NEGOTIATED_FC,
        PN_PIPE_SB_REQUIRED_FC_TX,
        PN_PIPE_SB_PREFERRED_FC_RX,
+       PN_PIPE_SB_ALIGNED_DATA,
 };
 
 /* Phonet pipe flow control models */
index e23e309..72db27e 100644 (file)
@@ -444,6 +444,7 @@ static int pep_connreq_rcv(struct sock *sk, struct sk_buff *skb)
        struct sockaddr_pn dst;
        u16 peer_type;
        u8 pipe_handle, enabled, n_sb;
+       u8 aligned = 0;
 
        if (!pskb_pull(skb, sizeof(*hdr) + 4))
                return -EINVAL;
@@ -482,6 +483,9 @@ static int pep_connreq_rcv(struct sock *sk, struct sk_buff *skb)
                                return -EINVAL;
                        peer_type = (peer_type & 0xff00) | data[0];
                        break;
+               case PN_PIPE_SB_ALIGNED_DATA:
+                       aligned = data[0] != 0;
+                       break;
                }
                n_sb--;
        }
@@ -513,6 +517,7 @@ static int pep_connreq_rcv(struct sock *sk, struct sk_buff *skb)
        newpn->rx_credits = 0;
        newpn->rx_fc = newpn->tx_fc = PN_LEGACY_FLOW_CONTROL;
        newpn->init_enable = enabled;
+       newpn->aligned = aligned;
 
        BUG_ON(!skb_queue_empty(&newsk->sk_receive_queue));
        skb_queue_head(&newsk->sk_receive_queue, skb);
@@ -832,11 +837,15 @@ static int pipe_skb_send(struct sock *sk, struct sk_buff *skb)
                return -ENOBUFS;
        }
 
-       skb_push(skb, 3);
+       skb_push(skb, 3 + pn->aligned);
        skb_reset_transport_header(skb);
        ph = pnp_hdr(skb);
        ph->utid = 0;
-       ph->message_id = PNS_PIPE_DATA;
+       if (pn->aligned) {
+               ph->message_id = PNS_PIPE_ALIGNED_DATA;
+               ph->data[0] = 0; /* padding */
+       } else
+               ph->message_id = PNS_PIPE_DATA;
        ph->pipe_handle = pn->pipe_handle;
 
        return pn_skb_send(sk, skb, &pipe_srv);
@@ -930,6 +939,9 @@ int pep_write(struct sock *sk, struct sk_buff *skb)
        struct sk_buff *rskb, *fs;
        int flen = 0;
 
+       if (pep_sk(sk)->aligned)
+               return pipe_skb_send(sk, skb);
+
        rskb = alloc_skb(MAX_PNPIPE_HEADER, GFP_ATOMIC);
        if (!rskb) {
                kfree_skb(skb);