diff options
author | David Howells <dhowells@redhat.com> | 2016-03-04 15:53:46 +0000 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2016-03-04 15:53:46 +0000 |
commit | 0d12f8a4027d021c9cc942f09f38d28288020c5d (patch) | |
tree | 751f54f93f15d9c0146cf2e4243dbfc25fd1cc6d /net/rxrpc/ar-output.c | |
parent | 4c198ad17a7253cc8ef3ff39bfe73d6b5e65ceef (diff) | |
download | linux-0d12f8a4027d021c9cc942f09f38d28288020c5d.tar.bz2 |
rxrpc: Keep the skb private record of the Rx header in host byte order
Currently, a copy of the Rx packet header is copied into the the sk_buff
private data so that we can advance the pointer into the buffer,
potentially discarding the original. At the moment, this copy is held in
network byte order, but this means we're doing a lot of unnecessary
translations.
The reasons it was done this way are that we need the values in network
byte order occasionally and we can use the copy, slightly modified, as part
of an iov array when sending an ack or an abort packet.
However, it seems more reasonable on review that it would be better kept in
host byte order and that we make up a new header when we want to send
another packet.
To this end, rename the original header struct to rxrpc_wire_header (with
BE fields) and institute a variant called rxrpc_host_header that has host
order fields. Change the struct in the sk_buff private data into an
rxrpc_host_header and translate the values when filling it in.
This further allows us to keep values kept in various structures in host
byte order rather than network byte order and allows removal of some fields
that are byteswapped duplicates.
Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'net/rxrpc/ar-output.c')
-rw-r--r-- | net/rxrpc/ar-output.c | 54 |
1 files changed, 37 insertions, 17 deletions
diff --git a/net/rxrpc/ar-output.c b/net/rxrpc/ar-output.c index 9e1527a6d026..353f5c9141ea 100644 --- a/net/rxrpc/ar-output.c +++ b/net/rxrpc/ar-output.c @@ -136,7 +136,7 @@ int rxrpc_client_sendmsg(struct rxrpc_sock *rx, struct rxrpc_transport *trans, struct rxrpc_call *call; unsigned long user_call_ID = 0; struct key *key; - __be16 service_id; + u16 service_id; u32 abort_code = 0; int ret; @@ -151,11 +151,11 @@ int rxrpc_client_sendmsg(struct rxrpc_sock *rx, struct rxrpc_transport *trans, bundle = NULL; if (trans) { - service_id = rx->service_id; + service_id = rx->srx.srx_service; if (msg->msg_name) { DECLARE_SOCKADDR(struct sockaddr_rxrpc *, srx, msg->msg_name); - service_id = htons(srx->srx_service); + service_id = srx->srx_service; } key = rx->key; if (key && !rx->key->payload.data[0]) @@ -348,7 +348,7 @@ int rxrpc_send_packet(struct rxrpc_transport *trans, struct sk_buff *skb) /* send the packet with the don't fragment bit set if we currently * think it's small enough */ - if (skb->len - sizeof(struct rxrpc_header) < trans->peer->maxdata) { + if (skb->len - sizeof(struct rxrpc_wire_header) < trans->peer->maxdata) { down_read(&trans->local->defrag_sem); /* send the packet by UDP * - returns -EMSGSIZE if UDP would have to fragment the packet @@ -480,8 +480,7 @@ static void rxrpc_queue_packet(struct rxrpc_call *call, struct sk_buff *skb, write_unlock_bh(&call->state_lock); } - _proto("Tx DATA %%%u { #%u }", - ntohl(sp->hdr.serial), ntohl(sp->hdr.seq)); + _proto("Tx DATA %%%u { #%u }", sp->hdr.serial, sp->hdr.seq); sp->need_resend = false; sp->resend_at = jiffies + rxrpc_resend_timeout; @@ -513,6 +512,29 @@ static void rxrpc_queue_packet(struct rxrpc_call *call, struct sk_buff *skb, } /* + * Convert a host-endian header into a network-endian header. + */ +static void rxrpc_insert_header(struct sk_buff *skb) +{ + struct rxrpc_wire_header whdr; + struct rxrpc_skb_priv *sp = rxrpc_skb(skb); + + whdr.epoch = htonl(sp->hdr.epoch); + whdr.cid = htonl(sp->hdr.cid); + whdr.callNumber = htonl(sp->hdr.callNumber); + whdr.seq = htonl(sp->hdr.seq); + whdr.serial = htonl(sp->hdr.serial); + whdr.type = sp->hdr.type; + whdr.flags = sp->hdr.flags; + whdr.userStatus = sp->hdr.userStatus; + whdr.securityIndex = sp->hdr.securityIndex; + whdr._rsvd = htons(sp->hdr._rsvd); + whdr.serviceId = htons(sp->hdr.serviceId); + + memcpy(skb->head, &whdr, sizeof(whdr)); +} + +/* * send data through a socket * - must be called in process context * - caller holds the socket locked @@ -650,17 +672,16 @@ static int rxrpc_send_data(struct rxrpc_sock *rx, seq = atomic_inc_return(&call->sequence); - sp->hdr.epoch = conn->epoch; - sp->hdr.cid = call->cid; + sp->hdr.epoch = conn->epoch; + sp->hdr.cid = call->cid; sp->hdr.callNumber = call->call_id; - sp->hdr.seq = htonl(seq); - sp->hdr.serial = - htonl(atomic_inc_return(&conn->serial)); - sp->hdr.type = RXRPC_PACKET_TYPE_DATA; + sp->hdr.seq = seq; + sp->hdr.serial = atomic_inc_return(&conn->serial); + sp->hdr.type = RXRPC_PACKET_TYPE_DATA; sp->hdr.userStatus = 0; sp->hdr.securityIndex = conn->security_ix; - sp->hdr._rsvd = 0; - sp->hdr.serviceId = conn->service_id; + sp->hdr._rsvd = 0; + sp->hdr.serviceId = call->service_id; sp->hdr.flags = conn->out_clientflag; if (msg_data_left(msg) == 0 && !more) @@ -673,12 +694,11 @@ static int rxrpc_send_data(struct rxrpc_sock *rx, ret = rxrpc_secure_packet( call, skb, skb->mark, - skb->head + sizeof(struct rxrpc_header)); + skb->head + sizeof(struct rxrpc_wire_header)); if (ret < 0) goto out; - memcpy(skb->head, &sp->hdr, - sizeof(struct rxrpc_header)); + rxrpc_insert_header(skb); rxrpc_queue_packet(call, skb, !msg_data_left(msg) && !more); skb = NULL; } |