Skip to content

Commit

Permalink
Increment IPv4 id fields during software segmentation
Browse files Browse the repository at this point in the history
This resolves #24, contributed by breakertt.
  • Loading branch information
johnousterhout committed Mar 9, 2023
1 parent da84be8 commit 76ab583
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 2 deletions.
13 changes: 13 additions & 0 deletions homa_offload.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,19 @@ struct sk_buff *homa_gso_segment(struct sk_buff *skb,
__skb_pull(skb, sizeof(struct data_header)
- sizeof(struct data_segment));
segs = skb_segment(skb, features);

/* Set incrementing ids in each of the segments (mimics behavior
* of Mellanox NICs and other segmenters).
*/
if (ip_hdr(segs)->version == 4) {
struct sk_buff *seg;
int i = 0;
for (seg = segs; seg != NULL; seg = seg->next) {
ip_hdr(seg)->id = htons(i);
i++;
}
}

tt_record("homa_gso_segment returning");
return segs;
}
Expand Down
21 changes: 19 additions & 2 deletions test/mock.c
Original file line number Diff line number Diff line change
Expand Up @@ -933,7 +933,24 @@ void *skb_put(struct sk_buff *skb, unsigned int len)
struct sk_buff *skb_segment(struct sk_buff *head_skb,
netdev_features_t features)
{
return NULL;
struct data_header h;
int offset, length;
struct sk_buff *skb1, *skb2;

/* Split the existing packet into two packets. */
memcpy(&h, skb_transport_header(head_skb), sizeof(h));
offset = ntohl(h.seg.offset);
length = ntohl(h.seg.segment_length);
h.seg.segment_length = htonl(length/2);
skb1 = mock_skb_new(&ipv6_hdr(head_skb)->saddr, &h.common, length/2,
offset);
offset += length/2;
h.seg.offset = htonl(offset);
skb2 = mock_skb_new(&ipv6_hdr(head_skb)->saddr, &h.common, length/2,
offset);
skb2->next = NULL;
skb1->next = skb2;
return skb1;
}

int sock_common_getsockopt(struct socket *sock, int level, int optname,
Expand Down Expand Up @@ -1125,7 +1142,7 @@ void mock_rcu_read_unlock(void)
/**
* mock_skb_new() - Allocate and return a packet buffer. The buffer is
* initialized as if it just arrived from the network.
* @saddr: IPV4 address to use as the sender of the packet, in
* @saddr: IPv6 address to use as the sender of the packet, in
* network byte order.
* @h: Header for the buffer; actual length and contents depend
* on the type.
Expand Down
17 changes: 17 additions & 0 deletions test/unit_homa_offload.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,23 @@ FIXTURE_TEARDOWN(homa_offload)
unit_teardown();
}

TEST_F(homa_offload, homa_gso_segment_set_ip_ids)
{
mock_ipv6 = false;
struct sk_buff *skb = mock_skb_new(&self->ip, &self->header.common,
1400, 2000);
int version = ip_hdr(skb)->version;
EXPECT_EQ(4, version);
struct sk_buff *segs = homa_gso_segment(skb, 0);
ASSERT_NE(NULL, segs);
ASSERT_NE(NULL, segs->next);
EXPECT_EQ(NULL, segs->next->next);
EXPECT_EQ(0, ntohs(ip_hdr(segs)->id));
EXPECT_EQ(1, ntohs(ip_hdr(segs->next)->id));
kfree_skb(skb);
kfree_skb(segs->next);
kfree_skb(segs);
}

TEST_F(homa_offload, homa_gro_receive__fast_grant_optimization)
{
Expand Down

0 comments on commit 76ab583

Please sign in to comment.