EM-ODP  3.7.0
Event Machine on ODP
event_machine_packet.c
1 /*
2  * Copyright (c) 2024, Nokia Solutions and Networks
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * * Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  * * Neither the name of the copyright holder nor the names of its
15  * contributors may be used to endorse or promote products derived
16  * from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include "em_include.h"
32 
33 static inline bool is_odp_packet(odp_event_t odp_event)
34 {
35  if (unlikely(odp_event == ODP_EVENT_INVALID ||
36  odp_event_type(odp_event) != ODP_EVENT_PACKET))
37  return false;
38 
39  return true;
40 }
41 
42 void *em_packet_pointer(em_event_t pktev)
43 {
44  odp_event_t odp_event = event_em2odp(pktev);
45 
46  if (EM_CHECK_LEVEL >= 3 &&
47  unlikely(!is_odp_packet(odp_event))) {
48  INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_PACKET_POINTER,
49  "Invalid packet event");
50  return NULL;
51  }
52 
53  odp_packet_t odp_pkt = odp_packet_from_event(odp_event);
54 
55  return odp_packet_data(odp_pkt);
56 }
57 
58 uint32_t em_packet_size(em_event_t pktev)
59 {
60  odp_event_t odp_event = event_em2odp(pktev);
61 
62  if (EM_CHECK_LEVEL >= 3 &&
63  unlikely(!is_odp_packet(odp_event))) {
64  INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_PACKET_SIZE,
65  "Invalid packet event");
66  return 0;
67  }
68 
69  odp_packet_t odp_pkt = odp_packet_from_event(odp_event);
70  uint32_t seg_len = odp_packet_seg_len(odp_pkt);
71 
72  return seg_len;
73 }
74 
75 void *em_packet_pointer_and_size(em_event_t pktev, uint32_t *size /*out*/)
76 {
77  odp_event_t odp_event = event_em2odp(pktev);
78 
79  if (EM_CHECK_LEVEL >= 3 &&
80  unlikely(!is_odp_packet(odp_event))) {
81  INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_PACKET_POINTER_AND_SIZE,
82  "Invalid packet event");
83  return NULL;
84  }
85 
86  odp_packet_t odp_pkt = odp_packet_from_event(odp_event);
87 
88  if (!size) {
89  /* User not interested in 'size',
90  * fall back to em_packet_pointer() functionality
91  */
92  return odp_packet_data(odp_pkt);
93  }
94 
95  return odp_packet_data_seg_len(odp_pkt, size /*out*/);
96 }
97 
98 void *em_packet_resize(em_event_t pktev, uint32_t size)
99 {
100  odp_event_t odp_event = event_em2odp(pktev);
101 
102  if (EM_CHECK_LEVEL >= 3 &&
103  unlikely(!is_odp_packet(odp_event))) {
104  INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_PACKET_RESIZE,
105  "Invalid packet event");
106  return NULL;
107  }
108 
109  odp_packet_t odp_pkt = odp_packet_from_event(odp_event);
110  uint32_t seg_len = odp_packet_seg_len(odp_pkt);
111  const void *tail;
112 
113  if (EM_CHECK_LEVEL >= 3) {
114  uint32_t tailroom = odp_packet_tailroom(odp_pkt);
115 
116  if (unlikely(size == 0 || size > seg_len + tailroom)) {
117  INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_PACKET_RESIZE,
118  "Invalid packet resize:%u > max:%u",
119  size, seg_len + tailroom);
120  return NULL;
121  }
122  }
123 
124  if (size > seg_len)
125  tail = odp_packet_push_tail(odp_pkt, size - seg_len);
126  else /* size <= seg_len */
127  tail = odp_packet_pull_tail(odp_pkt, seg_len - size);
128 
129  if (unlikely(!tail))
130  return NULL;
131 
132  return odp_packet_data(odp_pkt);
133 }
134 
135 uint32_t em_packet_headroom(em_event_t pktev)
136 {
137  odp_event_t odp_event = event_em2odp(pktev);
138 
139  if (EM_CHECK_LEVEL >= 3 &&
140  unlikely(!is_odp_packet(odp_event))) {
141  INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_PACKET_HEADROOM,
142  "Invalid packet event");
143  return 0;
144  }
145 
146  odp_packet_t odp_pkt = odp_packet_from_event(odp_event);
147 
148  return odp_packet_headroom(odp_pkt);
149 }
150 
151 uint32_t em_packet_tailroom(em_event_t pktev)
152 {
153  odp_event_t odp_event = event_em2odp(pktev);
154 
155  if (EM_CHECK_LEVEL >= 3 &&
156  unlikely(!is_odp_packet(odp_event))) {
157  INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_PACKET_TAILROOM,
158  "Invalid packet event");
159  return 0;
160  }
161 
162  odp_packet_t odp_pkt = odp_packet_from_event(odp_event);
163 
164  return odp_packet_tailroom(odp_pkt);
165 }
166 
167 void *em_packet_push_head(em_event_t pktev, uint32_t len)
168 {
169  odp_event_t odp_event = event_em2odp(pktev);
170 
171  if (EM_CHECK_LEVEL >= 3 &&
172  unlikely(!is_odp_packet(odp_event))) {
173  INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_PACKET_PUSH_HEAD,
174  "Invalid packet event");
175  return NULL;
176  }
177 
178  odp_packet_t odp_pkt = odp_packet_from_event(odp_event);
179  void *ptr = odp_packet_push_head(odp_pkt, len);
180 
181  if (EM_CHECK_LEVEL >= 3 && unlikely(!ptr)) {
182  INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_PACKET_PUSH_HEAD,
183  "packet push head failed, check len=%u", len);
184  return NULL;
185  }
186 
187  return ptr;
188 }
189 
190 void *em_packet_pull_head(em_event_t pktev, uint32_t len)
191 {
192  odp_event_t odp_event = event_em2odp(pktev);
193 
194  if (EM_CHECK_LEVEL >= 3 &&
195  unlikely(!is_odp_packet(odp_event))) {
196  INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_PACKET_PULL_HEAD,
197  "Invalid packet event");
198  return NULL;
199  }
200 
201  odp_packet_t odp_pkt = odp_packet_from_event(odp_event);
202  void *ptr = odp_packet_pull_head(odp_pkt, len);
203 
204  if (EM_CHECK_LEVEL >= 3 && unlikely(!ptr)) {
205  INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_PACKET_PULL_HEAD,
206  "packet pull head failed, check len=%u", len);
207  return NULL;
208  }
209 
210  return ptr;
211 }
212 
213 void *em_packet_push_tail(em_event_t pktev, uint32_t len)
214 {
215  odp_event_t odp_event = event_em2odp(pktev);
216 
217  if (EM_CHECK_LEVEL >= 3 &&
218  unlikely(!is_odp_packet(odp_event))) {
219  INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_PACKET_PUSH_TAIL,
220  "Invalid packet event");
221  return NULL;
222  }
223 
224  odp_packet_t odp_pkt = odp_packet_from_event(odp_event);
225  void *ptr = odp_packet_push_tail(odp_pkt, len);
226 
227  if (EM_CHECK_LEVEL >= 3 && unlikely(!ptr)) {
228  INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_PACKET_PUSH_TAIL,
229  "packet push tail failed, check len=%u", len);
230  return NULL;
231  }
232 
233  return ptr;
234 }
235 
236 void *em_packet_pull_tail(em_event_t pktev, uint32_t len)
237 {
238  odp_event_t odp_event = event_em2odp(pktev);
239 
240  if (EM_CHECK_LEVEL >= 3 &&
241  unlikely(!is_odp_packet(odp_event))) {
242  INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_PACKET_PULL_TAIL,
243  "Invalid packet event");
244  return NULL;
245  }
246 
247  odp_packet_t odp_pkt = odp_packet_from_event(odp_event);
248  void *ptr = odp_packet_pull_tail(odp_pkt, len);
249 
250  if (EM_CHECK_LEVEL >= 3 && unlikely(!ptr)) {
251  INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_PACKET_PULL_TAIL,
252  "packet pull tail failed, check len=%u", len);
253  return NULL;
254  }
255 
256  return ptr;
257 }
258 
259 em_status_t em_packet_reset(em_event_t pktev, uint32_t size)
260 {
261  odp_event_t odp_event = event_em2odp(pktev);
262 
263  RETURN_ERROR_IF(EM_CHECK_LEVEL >= 3 && !is_odp_packet(odp_event),
264  EM_ERR_BAD_ARG, EM_ESCOPE_PACKET_RESET,
265  "Invalid packet event");
266 
267  odp_packet_t odp_pkt = odp_packet_from_event(odp_event);
268  odp_pool_t odp_pool = odp_packet_pool(odp_pkt);
269  em_pool_t pool = pool_odp2em(odp_pool);
270  const mpool_elem_t *pool_elem = pool_elem_get(pool);
271 
272  RETURN_ERROR_IF(!pool_elem || (EM_CHECK_LEVEL >= 3 && !pool_allocated(pool_elem)),
273  EM_ERR_BAD_ID, EM_ESCOPE_PACKET_RESET,
274  "Invalid EM pool:%" PRI_POOL "", pool);
275 
276  const uint32_t push_head_len = pool_elem->align_offset;
277  uint32_t pull_tail_len;
278  uint32_t reset_len;
279 
280  if (size > push_head_len) {
281  reset_len = size - push_head_len;
282  pull_tail_len = 0;
283  } else {
284  reset_len = 1; /* min allowed */
285  pull_tail_len = push_head_len + 1 - size;
286  }
287 
288  int ret = odp_packet_reset(odp_pkt, reset_len);
289 
290  RETURN_ERROR_IF(ret, EM_ERR_LIB_FAILED, EM_ESCOPE_PACKET_RESET,
291  "odp-packet reset failed:%d", ret);
292 
293  /* Adjust event payload start-address based on alignment config */
294  if (push_head_len) {
295  const void *ptr = odp_packet_push_head(odp_pkt, push_head_len);
296 
297  RETURN_ERROR_IF(EM_CHECK_LEVEL >= 3 && !ptr,
298  EM_ERR_LIB_FAILED, EM_ESCOPE_PACKET_RESET,
299  "odp_packet_push_head() failed");
300  }
301  if (pull_tail_len) {
302  const void *ptr = odp_packet_pull_tail(odp_pkt, pull_tail_len);
303 
304  RETURN_ERROR_IF(EM_CHECK_LEVEL >= 3 && !ptr,
305  EM_ERR_LIB_FAILED, EM_ESCOPE_PACKET_RESET,
306  "odp_packet_pull_tail() failed");
307  }
308 
309  /*
310  * Set the pkt user ptr to be able to recognize pkt-events that
311  * EM has created vs pkts from pkt-input that needs their
312  * ev-hdrs to be initialized.
313  */
314  odp_packet_user_flag_set(odp_pkt, USER_FLAG_SET);
315 
316  event_hdr_t *const ev_hdr = odp_packet_user_area(odp_pkt);
317  ev_hdr_user_area_t uarea_save = ev_hdr->user_area;
318 
319  ev_hdr->event_size = size; /* store new 'original' size */
320  ev_hdr->egrp = EM_EVENT_GROUP_UNDEF;
321  ev_hdr->user_area.all = 0;
322  ev_hdr->user_area.size = uarea_save.size;
323  ev_hdr->user_area.isinit = 1;
324 
325  return EM_OK;
326 }
em_packet_push_tail
void * em_packet_push_tail(em_event_t pktev, uint32_t len)
Push out the end of the packet into the tailroom.
Definition: event_machine_packet.c:213
EM_OK
#define EM_OK
Definition: event_machine_types.h:329
event_hdr::event_size
uint32_t event_size
Definition: em_event_types.h:255
em_packet_pointer
void * em_packet_pointer(em_event_t pktev)
Definition: event_machine_packet.c:42
ev_hdr_user_area_t
Definition: em_event_types.h:162
USER_FLAG_SET
#define USER_FLAG_SET
Definition: em_event_types.h:56
PRI_POOL
#define PRI_POOL
Definition: event_machine_hw_types.h:62
EM_ERR_LIB_FAILED
@ EM_ERR_LIB_FAILED
Definition: event_machine_hw_types.h:291
em_packet_reset
em_status_t em_packet_reset(em_event_t pktev, uint32_t size)
Definition: event_machine_packet.c:259
em_packet_headroom
uint32_t em_packet_headroom(em_event_t pktev)
Packet event headroom length.
Definition: event_machine_packet.c:135
event_hdr
Definition: em_event_types.h:184
mpool_elem_t
Definition: em_pool_types.h:47
RETURN_ERROR_IF
#define RETURN_ERROR_IF(cond, error, escope, fmt,...)
Definition: em_error.h:50
EM_ERR_BAD_ID
@ EM_ERR_BAD_ID
Definition: event_machine_hw_types.h:265
em_packet_pull_tail
void * em_packet_pull_tail(em_event_t pktev, uint32_t len)
Definition: event_machine_packet.c:236
INTERNAL_ERROR
#define INTERNAL_ERROR(error, escope, fmt,...)
Definition: em_error.h:43
mpool_elem_t::align_offset
uint32_t align_offset
Definition: em_pool_types.h:51
event_hdr::user_area
ev_hdr_user_area_t user_area
Definition: em_event_types.h:277
em_packet_push_head
void * em_packet_push_head(em_event_t pktev, uint32_t len)
Push out the beginning of the packet into the headroom.
Definition: event_machine_packet.c:167
em_status_t
uint32_t em_status_t
Definition: event_machine_types.h:321
em_packet_resize
void * em_packet_resize(em_event_t pktev, uint32_t size)
Resize a packet event.
Definition: event_machine_packet.c:98
EM_CHECK_LEVEL
#define EM_CHECK_LEVEL
Definition: event_machine_config.h:253
event_hdr::egrp
em_event_group_t egrp
Definition: em_event_types.h:265
em_include.h
em_packet_tailroom
uint32_t em_packet_tailroom(em_event_t pktev)
Packet event tailroom length.
Definition: event_machine_packet.c:151
EM_ERR_BAD_ARG
@ EM_ERR_BAD_ARG
Definition: event_machine_hw_types.h:261
em_packet_pointer_and_size
void * em_packet_pointer_and_size(em_event_t pktev, uint32_t *size)
Get the packet event data pointer as well as the packet size.
Definition: event_machine_packet.c:75
ev_hdr_user_area_t::size
uint32_t size
Definition: em_event_types.h:170
em_packet_pull_head
void * em_packet_pull_head(em_event_t pktev, uint32_t len)
Pull in the beginning of the packet from the headroom.
Definition: event_machine_packet.c:190
em_packet_size
uint32_t em_packet_size(em_event_t pktev)
Get the packet size.
Definition: event_machine_packet.c:58
EM_EVENT_GROUP_UNDEF
#define EM_EVENT_GROUP_UNDEF
Definition: event_machine_types.h:141
ev_hdr_user_area_t::isinit
uint32_t isinit
Definition: em_event_types.h:168