API Reference Manual 1.51.0
Loading...
Searching...
No Matches
odp_ipfragreass_fragment.c
1/* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright (c) 2017-2018 Linaro Limited
3 */
4
7#include <stdio.h>
8#include <assert.h>
9
10#include "odp_ipfragreass_ip.h"
11#include "odp_ipfragreass_fragment.h"
12
13int fragment_ipv4_packet(odp_packet_t orig_packet, odp_packet_t *out,
14 int *out_len)
15{
16 int fragments = 0;
17 odp_bool_t first_fragment = 1;
18 odph_ipv4hdr_t *orig_header = odp_packet_data(orig_packet);
19 uint32_t header_len = ipv4hdr_ihl(*orig_header);
20 uint32_t orig_len = odp_packet_len(orig_packet);
21 uint32_t bytes_remaining = orig_len - header_len;
22 uint32_t frag_offset = 0;
23 odp_packet_t frag = orig_packet;
25
26 if (bytes_remaining <= MTU)
27 return -1;
28
29 /*
30 * The main fragmentation loop (continue until all bytes from the
31 * original payload have been assigned to a fragment)
32 */
33 while (bytes_remaining) {
34 odph_ipv4hdr_t *header;
35 uint32_t frag_len;
36
37 frag_len = (bytes_remaining > MTU ? (MTU + header_len)
38 : (bytes_remaining
39 + header_len));
40 bytes_remaining -= (frag_len - header_len);
41 if (bytes_remaining) {
42 uint32_t split_point;
43 int split_success;
44
45 split_point = first_fragment ? (frag_len)
46 : (frag_len - header_len);
47 split_success = odp_packet_split(&frag, split_point,
48 &rest);
49 if (split_success < 0) {
50 fprintf(stderr,
51 "ERROR: odp_packet_split\n");
52 return -1;
53 } else if (first_fragment && split_success > 0) {
54 orig_header = odp_packet_data(frag);
55 }
56 }
57
58 /* Add a header to the packet if necessary */
59 if (first_fragment) {
60 first_fragment = 0;
61 } else {
62 if (odp_packet_extend_head(&frag, header_len, NULL,
63 NULL) < 0) {
64 fprintf(stderr,
65 "ERROR: odp_packet_extend_head\n");
66 return -1;
67 }
68 if (odp_packet_copy_from_mem(frag, 0, header_len,
69 orig_header)) {
70 fprintf(stderr,
71 "ERROR: odp_packet_copy_from_mem\n");
72 return -1;
73 }
74 }
75
76 /* Update the header */
77 header = odp_packet_data(frag);
78 ipv4hdr_set_more_fragments(header, bytes_remaining != 0);
79 header->tot_len = odp_cpu_to_be_16(frag_len);
80 ipv4hdr_set_fragment_offset_oct(header, (frag_offset / 8));
81 assert((bytes_remaining == 0) ||
82 (odp_packet_len(frag) == (MTU + header_len)));
83 assert((bytes_remaining != 0) ||
84 (ipv4hdr_reass_payload_len(*header) + header_len
85 == orig_len));
87 header->chksum = 0;
88 odph_ipv4_csum_update(frag);
89
90 out[fragments++] = frag;
91 frag = rest;
92 frag_offset += (frag_len - header_len);
93 }
94
95 if (out_len)
96 *out_len = fragments;
97
98 return 0;
99}
odp_u16be_t odp_cpu_to_be_16(uint16_t cpu16)
Convert cpu native uint16_t to 16bit big endian.
int odp_packet_l3_offset_set(odp_packet_t pkt, uint32_t offset)
Set layer 3 start offset.
void * odp_packet_data(odp_packet_t pkt)
Packet data pointer.
int odp_packet_extend_head(odp_packet_t *pkt, uint32_t len, void **data_ptr, uint32_t *seg_len)
Extend packet head.
int odp_packet_split(odp_packet_t *pkt, uint32_t len, odp_packet_t *tail)
Split packet into two packets.
uint32_t odp_packet_len(odp_packet_t pkt)
Packet data length.
int odp_packet_copy_from_mem(odp_packet_t pkt, uint32_t offset, uint32_t len, const void *src)
Copy data from memory to packet.
#define ODP_PACKET_INVALID
Invalid packet.
bool odp_bool_t
Boolean type.