1010#include "homa_wire.h"
1111
1212#ifndef __STRIP__ /* See strip.py */
13+ #include <net/udp.h>
1314#include "homa_pacer.h"
1415#include "homa_qdisc.h"
1516#include "homa_skb.h"
@@ -49,6 +50,45 @@ static inline void homa_set_hijack(struct sk_buff *skb, struct homa_peer *peer,
4950 h -> checksum = ~tcp_v4_check (skb -> len , peer -> flow .u .ip4 .saddr ,
5051 peer -> flow .u .ip4 .daddr , 0 );
5152}
53+
54+ /**
55+ * homa_set_udp_hijack() - Set fields in an outgoing Homa packet that are
56+ * needed for UDP hijacking to work properly. Similar to homa_set_hijack()
57+ * but uses IPPROTO_UDP for checksumming and writes a UDP length/checksum
58+ * overlay at bytes 4-7 of the transport header.
59+ * @skb: Packet buffer in which to set fields.
60+ * @peer: Peer that contains source and destination addresses for the packet.
61+ * @ipv6: True means the packet is going to be sent via IPv6; false means
62+ * IPv4.
63+ */
64+ static inline void homa_set_udp_hijack (struct sk_buff * skb ,
65+ struct homa_peer * peer , bool ipv6 )
66+ {
67+ struct homa_common_hdr * h ;
68+ __be16 * udp_len_csum ;
69+
70+ h = (struct homa_common_hdr * )skb_transport_header (skb );
71+ h -> flags = HOMA_UDP_FLAGS ;
72+ h -> urgent = htons (HOMA_UDP_URGENT );
73+
74+ /* Write UDP length and checksum at bytes 4-7 of transport header. */
75+ udp_len_csum = (__be16 * )(skb_transport_header (skb ) + 4 );
76+ udp_len_csum [0 ] = htons (skb -> len ); /* UDP length */
77+ udp_len_csum [1 ] = 0 ; /* UDP checksum (0 = none) */
78+
79+ /* Arrange for proper UDP checksumming. */
80+ skb -> ip_summed = CHECKSUM_PARTIAL ;
81+ skb -> csum_start = skb_transport_header (skb ) - skb -> head ;
82+ skb -> csum_offset = offsetof(struct homa_common_hdr , checksum );
83+ if (ipv6 )
84+ h -> checksum = ~csum_ipv6_magic (& peer -> flow .u .ip6 .saddr ,
85+ & peer -> flow .u .ip6 .daddr ,
86+ skb -> len , IPPROTO_UDP , 0 );
87+ else
88+ h -> checksum = ~udp_v4_check (skb -> len ,
89+ peer -> flow .u .ip4 .saddr ,
90+ peer -> flow .u .ip4 .daddr , 0 );
91+ }
5292#endif /* See strip.py */
5393
5494/**
@@ -204,7 +244,10 @@ struct sk_buff *homa_tx_data_pkt_alloc(struct homa_rpc *rpc,
204244 IF_NO_STRIP (h -> cutoff_version = rpc -> peer -> cutoff_version );
205245 h -> retransmit = 0 ;
206246#ifndef __STRIP__ /* See strip.py */
207- h -> seg .offset = htonl (-1 );
247+ if (hsk -> sock .sk_protocol == IPPROTO_UDP )
248+ h -> seg .offset = htonl (offset );
249+ else
250+ h -> seg .offset = htonl (-1 );
208251#else /* See strip.py */
209252 h -> seg .offset = htonl (offset );
210253#endif /* See strip.py */
@@ -219,7 +262,8 @@ struct sk_buff *homa_tx_data_pkt_alloc(struct homa_rpc *rpc,
219262 homa_info -> rpc = rpc ;
220263
221264#ifndef __STRIP__ /* See strip.py */
222- if (segs > 1 && hsk -> sock .sk_protocol != IPPROTO_TCP ) {
265+ if (segs > 1 && hsk -> sock .sk_protocol != IPPROTO_TCP
266+ && hsk -> sock .sk_protocol != IPPROTO_UDP ) {
223267#else /* See strip.py */
224268 if (segs > 1 ) {
225269#endif /* See strip.py */
@@ -322,10 +366,13 @@ int homa_message_out_fill(struct homa_rpc *rpc, struct iov_iter *iter, int xmit)
322366 * if no hijacking).
323367 */
324368 if (rpc -> hsk -> sock .sk_protocol == IPPROTO_TCP ) {
325- /* Hijacking */
369+ /* TCP Hijacking */
326370 segs_per_gso = gso_size - rpc -> hsk -> ip_header_length
327371 - sizeof (struct homa_data_hdr );
328372 do_div (segs_per_gso , max_seg_data );
373+ } else if (rpc -> hsk -> sock .sk_protocol == IPPROTO_UDP ) {
374+ /* UDP Hijacking: one segment per GSO */
375+ segs_per_gso = 1 ;
329376 } else {
330377 /* No hijacking */
331378 segs_per_gso = gso_size - rpc -> hsk -> ip_header_length -
@@ -509,12 +556,18 @@ int __homa_xmit_control(void *contents, size_t length, struct homa_peer *peer,
509556 homa_set_doff (skb , length );
510557#ifndef __STRIP__ /* See strip.py */
511558 if (hsk -> inet .sk .sk_family == AF_INET6 ) {
512- homa_set_hijack (skb , peer , true);
559+ if (hsk -> sock .sk_protocol == IPPROTO_UDP )
560+ homa_set_udp_hijack (skb , peer , true);
561+ else
562+ homa_set_hijack (skb , peer , true);
513563 result = ip6_xmit (& hsk -> inet .sk , skb , & peer -> flow .u .ip6 , 0 ,
514564 NULL , hsk -> homa -> priority_map [priority ] << 5 ,
515565 0 );
516566 } else {
517- homa_set_hijack (skb , peer , false);
567+ if (hsk -> sock .sk_protocol == IPPROTO_UDP )
568+ homa_set_udp_hijack (skb , peer , false);
569+ else
570+ homa_set_hijack (skb , peer , false);
518571
519572 /* This will find its way to the DSCP field in the IPv4 hdr. */
520573 hsk -> inet .tos = hsk -> homa -> priority_map [priority ] << 5 ;
@@ -721,7 +774,10 @@ void __homa_xmit_data(struct sk_buff *skb, struct homa_rpc *rpc)
721774 tt_addr (rpc -> peer -> addr ), rpc -> id ,
722775 homa_get_skb_info (skb )-> offset );
723776#ifndef __STRIP__ /* See strip.py */
724- homa_set_hijack (skb , rpc -> peer , true);
777+ if (rpc -> hsk -> sock .sk_protocol == IPPROTO_UDP )
778+ homa_set_udp_hijack (skb , rpc -> peer , true);
779+ else
780+ homa_set_hijack (skb , rpc -> peer , true);
725781 err = ip6_xmit (& rpc -> hsk -> inet .sk , skb , & rpc -> peer -> flow .u .ip6 ,
726782 0 , NULL ,
727783 rpc -> hsk -> homa -> priority_map [priority ] << 5 , 0 );
@@ -736,7 +792,10 @@ void __homa_xmit_data(struct sk_buff *skb, struct homa_rpc *rpc)
736792 homa_get_skb_info (skb )-> offset );
737793
738794#ifndef __STRIP__ /* See strip.py */
739- homa_set_hijack (skb , rpc -> peer , false);
795+ if (rpc -> hsk -> sock .sk_protocol == IPPROTO_UDP )
796+ homa_set_udp_hijack (skb , rpc -> peer , false);
797+ else
798+ homa_set_hijack (skb , rpc -> peer , false);
740799 rpc -> hsk -> inet .tos =
741800 rpc -> hsk -> homa -> priority_map [priority ] << 5 ;
742801 err = ip_queue_xmit (& rpc -> hsk -> inet .sk , skb , & rpc -> peer -> flow );
0 commit comments