Skip to content

Commit 9721ca4

Browse files
committed
Use csp_buffer_get_always only when incoming packets is not to be routed
The functionality is used to stall a module in case it is running out of buffers, potentially causing a reboot. Nevertheless, running out of buffers is a valid situation if a module is routing between two physical networks with different capatilities (e.g. CAN vs ETH).
1 parent 8d02a09 commit 9721ca4

9 files changed

Lines changed: 167 additions & 117 deletions

File tree

include/csp/csp_id.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@ extern "C" {
77
#include <csp/csp.h>
88

99
void csp_id_prepend(csp_packet_t * packet);
10+
csp_id_t csp_id_extract(const uint8_t * data);
1011
int csp_id_strip(csp_packet_t * packet);
1112
int csp_id_setup_rx(csp_packet_t * packet);
1213
unsigned int csp_id_get_host_bits(void);
1314
unsigned int csp_id_get_max_nodeid(void);
1415
unsigned int csp_id_get_max_port(void);
1516

1617
int csp_id_is_broadcast(uint16_t addr, csp_iface_t * iface);
18+
int csp_id_get_header_size(void);
1719

1820
#ifdef __cplusplus
1921
}

src/csp_id.c

Lines changed: 55 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@
66
*/
77

88
#include <endian.h>
9+
#include <string.h>
10+
911
#include <csp/csp.h>
12+
#include <csp/csp_id.h>
1013

1114
/**
1215
* CSP 1.x
@@ -40,46 +43,42 @@
4043
static void csp_id1_prepend(csp_packet_t * packet) {
4144

4245
/* Pack into 32-bit using host endian */
43-
uint32_t id1 = (((uint32_t)(packet->id.pri) << CSP_ID1_PRIO_OFFSET) |
44-
((uint32_t)(packet->id.dst) << CSP_ID1_DST_OFFSET) |
45-
((uint32_t)(packet->id.src) << CSP_ID1_SRC_OFFSET) |
46-
((uint32_t)(packet->id.dport) << CSP_ID1_DPORT_OFFSET) |
47-
((uint32_t)(packet->id.sport) << CSP_ID1_SPORT_OFFSET) |
48-
((uint32_t)(packet->id.flags) << CSP_ID1_FLAGS_OFFSET));
46+
uint32_t id1_raw = (((uint32_t)(packet->id.pri) << CSP_ID1_PRIO_OFFSET) |
47+
((uint32_t)(packet->id.dst) << CSP_ID1_DST_OFFSET) |
48+
((uint32_t)(packet->id.src) << CSP_ID1_SRC_OFFSET) |
49+
((uint32_t)(packet->id.dport) << CSP_ID1_DPORT_OFFSET) |
50+
((uint32_t)(packet->id.sport) << CSP_ID1_SPORT_OFFSET) |
51+
((uint32_t)(packet->id.flags) << CSP_ID1_FLAGS_OFFSET));
4952

5053
/* Convert to big / network endian */
51-
id1 = htobe32(id1);
54+
uint32_t id1 = htobe32(id1_raw);
5255

5356
packet->frame_begin = packet->data - CSP_ID1_HEADER_SIZE;
5457
packet->frame_length = packet->length + CSP_ID1_HEADER_SIZE;
5558

5659
memcpy(packet->frame_begin, &id1, CSP_ID1_HEADER_SIZE);
5760
}
5861

59-
static int csp_id1_strip(csp_packet_t * packet) {
60-
61-
if (packet->frame_length < CSP_ID1_HEADER_SIZE) {
62-
return -1;
63-
}
62+
static csp_id_t csp_id1_extract(const uint8_t * data) {
6463

6564
/* Get 32 bit in network byte order */
66-
uint32_t id1 = 0;
67-
memcpy(&id1, packet->frame_begin, CSP_ID1_HEADER_SIZE);
68-
packet->length = packet->frame_length - CSP_ID1_HEADER_SIZE;
65+
uint32_t id1_raw = 0;
66+
memcpy(&id1_raw, data, CSP_ID1_HEADER_SIZE);
6967

7068
/* Convert to host order */
71-
id1 = be32toh(id1);
69+
uint32_t id1 = be32toh(id1_raw);
7270

7371
/* Parse header:
7472
* Now in easy to work with in 32 bit register */
75-
packet->id.pri = (id1 >> CSP_ID1_PRIO_OFFSET) & CSP_ID1_PRIO_MASK;
76-
packet->id.dst = (id1 >> CSP_ID1_DST_OFFSET) & CSP_ID1_DST_MASK;
77-
packet->id.src = (id1 >> CSP_ID1_SRC_OFFSET) & CSP_ID1_SRC_MASK;
78-
packet->id.dport = (id1 >> CSP_ID1_DPORT_OFFSET) & CSP_ID1_DPORT_MASK;
79-
packet->id.sport = (id1 >> CSP_ID1_SPORT_OFFSET) & CSP_ID1_SPORT_MASK;
80-
packet->id.flags = (id1 >> CSP_ID1_FLAGS_OFFSET) & CSP_ID1_FLAGS_MASK;
81-
82-
return 0;
73+
csp_id_t id;
74+
id.pri = (id1 >> CSP_ID1_PRIO_OFFSET) & CSP_ID1_PRIO_MASK;
75+
id.dst = (id1 >> CSP_ID1_DST_OFFSET) & CSP_ID1_DST_MASK;
76+
id.src = (id1 >> CSP_ID1_SRC_OFFSET) & CSP_ID1_SRC_MASK;
77+
id.dport = (id1 >> CSP_ID1_DPORT_OFFSET) & CSP_ID1_DPORT_MASK;
78+
id.sport = (id1 >> CSP_ID1_SPORT_OFFSET) & CSP_ID1_SPORT_MASK;
79+
id.flags = (id1 >> CSP_ID1_FLAGS_OFFSET) & CSP_ID1_FLAGS_MASK;
80+
81+
return id;
8382
}
8483

8584
static void csp_id1_setup_rx(csp_packet_t * packet) {
@@ -136,17 +135,12 @@ static void csp_id2_prepend(csp_packet_t * packet) {
136135
memcpy(packet->frame_begin, &id2, CSP_ID2_HEADER_SIZE);
137136
}
138137

139-
static int csp_id2_strip(csp_packet_t * packet) {
140-
141-
if (packet->frame_length < CSP_ID2_HEADER_SIZE) {
142-
return -1;
143-
}
138+
static csp_id_t csp_id2_extract(const uint8_t* data) {
144139

145140
/* Get 48 bit in network byte order:
146141
* Most significant byte ends in byte 0 */
147142
uint64_t id2 = 0;
148-
memcpy(&id2, packet->frame_begin, CSP_ID2_HEADER_SIZE);
149-
packet->length = packet->frame_length - CSP_ID2_HEADER_SIZE;
143+
memcpy(&id2, data, CSP_ID2_HEADER_SIZE);
150144

151145
/* Convert to host order:
152146
* Most significant byte ends in byte 7, we then shift down
@@ -155,14 +149,15 @@ static int csp_id2_strip(csp_packet_t * packet) {
155149

156150
/* Parse header:
157151
* Now in easy to work with in 32 bit register */
158-
packet->id.pri = (id2 >> CSP_ID2_PRIO_OFFSET) & CSP_ID2_PRIO_MASK;
159-
packet->id.dst = (id2 >> CSP_ID2_DST_OFFSET) & CSP_ID2_DST_MASK;
160-
packet->id.src = (id2 >> CSP_ID2_SRC_OFFSET) & CSP_ID2_SRC_MASK;
161-
packet->id.dport = (id2 >> CSP_ID2_DPORT_OFFSET) & CSP_ID2_DPORT_MASK;
162-
packet->id.sport = (id2 >> CSP_ID2_SPORT_OFFSET) & CSP_ID2_SPORT_MASK;
163-
packet->id.flags = (id2 >> CSP_ID2_FLAGS_OFFSET) & CSP_ID2_FLAGS_MASK;
164-
165-
return 0;
152+
csp_id_t id;
153+
id.pri = (id2 >> CSP_ID2_PRIO_OFFSET) & CSP_ID2_PRIO_MASK;
154+
id.dst = (id2 >> CSP_ID2_DST_OFFSET) & CSP_ID2_DST_MASK;
155+
id.src = (id2 >> CSP_ID2_SRC_OFFSET) & CSP_ID2_SRC_MASK;
156+
id.dport = (id2 >> CSP_ID2_DPORT_OFFSET) & CSP_ID2_DPORT_MASK;
157+
id.sport = (id2 >> CSP_ID2_SPORT_OFFSET) & CSP_ID2_SPORT_MASK;
158+
id.flags = (id2 >> CSP_ID2_FLAGS_OFFSET) & CSP_ID2_FLAGS_MASK;
159+
160+
return id;
166161
}
167162

168163
static void csp_id2_setup_rx(csp_packet_t * packet) {
@@ -186,13 +181,22 @@ void csp_id_prepend(csp_packet_t * packet) {
186181
}
187182
}
188183

189-
int csp_id_strip(csp_packet_t * packet) {
190-
packet->timestamp_rx = 0;
184+
csp_id_t csp_id_extract(const uint8_t * data) {
191185
if (csp_conf.version == 2) {
192-
return csp_id2_strip(packet);
186+
return csp_id2_extract(data);
193187
} else {
194-
return csp_id1_strip(packet);
188+
return csp_id1_extract(data);
189+
}
190+
}
191+
192+
int csp_id_strip(csp_packet_t * packet) {
193+
if (packet->frame_length < csp_id_get_header_size()) {
194+
return -1;
195195
}
196+
197+
packet->id = csp_id_extract(packet->frame_begin);
198+
packet->length = packet->frame_length - csp_id_get_header_size();
199+
return 0;
196200
}
197201

198202
int csp_id_setup_rx(csp_packet_t * packet) {
@@ -241,3 +245,11 @@ int csp_id_is_broadcast(uint16_t addr, csp_iface_t * iface) {
241245
}
242246
return 0;
243247
}
248+
249+
int csp_id_get_header_size(void) {
250+
if (csp_conf.version == 2) {
251+
return CSP_ID2_HEADER_SIZE;
252+
} else {
253+
return CSP_ID1_HEADER_SIZE;
254+
}
255+
}

src/interfaces/csp_if_can.c

Lines changed: 60 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,21 @@ int csp_can1_rx(csp_iface_t * iface, uint32_t id, const uint8_t * data, uint8_t
5959
csp_packet_t * packet = csp_can_pbuf_find(ifdata, id, CFP_ID_CONN_MASK, task_woken);
6060
if (packet == NULL) {
6161
if (CFP_TYPE(id) == CFP_BEGIN) {
62-
packet = csp_can_pbuf_new(ifdata, id, task_woken);
62+
uint8_t header[CFP1_CSP_HEADER_SIZE];
63+
/* Copy first 4 from data as they represent the CSP header, the data field is in network order */
64+
memcpy(header, data, CFP1_CSP_HEADER_SIZE);
65+
csp_id_t csp_id = csp_id_extract(header);
66+
packet = csp_can_pbuf_new(ifdata, id, csp_id, task_woken);
67+
if (packet == NULL) {
68+
iface->drop++;
69+
return CSP_ERR_NOBUFS;
70+
}
71+
72+
csp_id_setup_rx(packet);
73+
packet->id = csp_id;
74+
75+
memcpy(packet->frame_begin, data, CFP1_CSP_HEADER_SIZE);
76+
packet->frame_length += CFP1_CSP_HEADER_SIZE;
6377
} else {
6478
iface->frame++;
6579
return CSP_ERR_INVAL;
@@ -81,14 +95,8 @@ int csp_can1_rx(csp_iface_t * iface, uint32_t id, const uint8_t * data, uint8_t
8195
break;
8296
}
8397

84-
csp_id_setup_rx(packet);
85-
86-
/* Copy CSP identifier (header) */
87-
memcpy(packet->frame_begin, data, CFP1_CSP_HEADER_SIZE);
88-
packet->frame_length += CFP1_CSP_HEADER_SIZE;
89-
9098
/* Copy CSP length (of data) */
91-
memcpy(&(packet->length), data + CFP1_CSP_HEADER_SIZE, sizeof(packet->length));
99+
memcpy(&(packet->length), data + CFP1_CSP_HEADER_SIZE, CFP1_DATA_LEN_SIZE);
92100
packet->length = be16toh(packet->length);
93101

94102
/* Overflow: check if incoming frame data length is larger than buffer length */
@@ -269,50 +277,56 @@ int csp_can2_rx(csp_iface_t * iface, uint32_t id, const uint8_t * data, uint8_t
269277
csp_packet_t * packet = csp_can_pbuf_find(ifdata, id, CFP2_ID_CONN_MASK, task_woken);
270278
if (packet == NULL) {
271279
if (id & (CFP2_BEGIN_MASK << CFP2_BEGIN_OFFSET)) {
272-
packet = csp_can_pbuf_new(ifdata, id, task_woken);
273-
} else {
274-
iface->frame++;
275-
return CSP_ERR_INVAL;
276-
}
277-
}
278280

281+
/* Discard packet if DLC is less than CSP id + CSP length fields */
282+
if (dlc < 4) {
283+
csp_dbg_can_errno = CSP_DBG_CAN_ERR_SHORT_BEGIN;
284+
iface->frame++;
285+
return CSP_ERR_INVAL;
286+
}
279287

280-
/* BEGIN */
281-
if (id & (CFP2_BEGIN_MASK << CFP2_BEGIN_OFFSET)) {
288+
/* Copy first 2 bytes from CFP 2.0 header:
289+
* Because the id field has already been converted in memory to a 32-bit
290+
* host-order field, extract the first two bytes and convert back to
291+
* network order */
292+
uint8_t header[6];
293+
uint16_t first_two = id >> CFP2_DST_OFFSET;
294+
first_two = htobe16(first_two);
295+
memcpy(header, &first_two, 2);
296+
297+
/* Copy next 4 from data, the data field is in network order */
298+
memcpy(&header[2], data, 4);
299+
300+
/* Move RX offset for incoming data */
301+
data += 4;
302+
dlc -= 4;
303+
304+
/* Create CSP header info from the first bytes received */
305+
csp_id_t csp_id = csp_id_extract(header);
306+
packet = csp_can_pbuf_new(ifdata, id, csp_id, task_woken);
307+
if (packet == NULL) {
308+
iface->drop++;
309+
return CSP_ERR_NOBUFS;
310+
}
311+
312+
/* Prepare new CSP packet by adding header as extracted */
313+
csp_id_setup_rx(packet);
314+
packet->id = csp_id;
315+
memcpy(packet->frame_begin, header, csp_id_get_header_size());
316+
packet->frame_length = csp_id_get_header_size();
317+
packet->length = 0;
282318

283-
/* Discard packet if DLC is less than CSP id + CSP length fields */
284-
if (dlc < 4) {
285-
csp_dbg_can_errno = CSP_DBG_CAN_ERR_SHORT_BEGIN;
319+
/* Set next expected fragment counter to be 1 */
320+
packet->rx_count = 1;
321+
} else {
286322
iface->frame++;
287-
csp_can_pbuf_free(ifdata, packet, 1, task_woken);
288323
return CSP_ERR_INVAL;
289324
}
325+
}
290326

291-
csp_id_setup_rx(packet);
292-
293-
/* Copy first 2 bytes from CFP 2.0 header:
294-
* Because the id field has already been converted in memory to a 32-bit
295-
* host-order field, extract the first two bytes and convert back to
296-
* network order */
297-
uint16_t first_two = id >> CFP2_DST_OFFSET;
298-
first_two = htobe16(first_two);
299-
memcpy(packet->frame_begin, &first_two, 2);
300-
301-
/* Copy next 4 from data, the data field is in network order */
302-
memcpy(&packet->frame_begin[2], data, 4);
303-
304-
packet->frame_length = 6;
305-
packet->length = 0;
306-
307-
/* Move RX offset for incoming data */
308-
data += 4;
309-
dlc -= 4;
310-
311-
/* Set next expected fragment counter to be 1 */
312-
packet->rx_count = 1;
313327

314-
/* FRAGMENT */
315-
} else {
328+
/* FRAGMENT */
329+
if (!(id & (CFP2_BEGIN_MASK << CFP2_BEGIN_OFFSET))) {
316330

317331
int fragment_counter = (id >> CFP2_FC_OFFSET) & CFP2_FC_MASK;
318332

@@ -346,8 +360,8 @@ int csp_can2_rx(csp_iface_t * iface, uint32_t id, const uint8_t * data, uint8_t
346360
/* END */
347361
if (id & (CFP2_END_MASK << CFP2_END_OFFSET)) {
348362

349-
/* Parse CSP header into csp_id type */
350-
csp_id_strip(packet);
363+
/* Extract data length */
364+
packet->length = packet->frame_length - csp_id_get_header_size();
351365

352366
/* Rewrite incoming L2 broadcast to local node */
353367
if (packet->id.dst == 0x3FFF) {

src/interfaces/csp_if_can_pbuf.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <csp/csp_error.h>
77
#include <csp/arch/csp_time.h>
88
#include <csp/interfaces/csp_if_can.h>
9+
#include <csp/csp_iflist.h>
910

1011
/* Buffer element timeout in ms */
1112
#define PBUF_TIMEOUT_MS 1000
@@ -43,13 +44,24 @@ void csp_can_pbuf_free(csp_can_interface_data_t * ifdata, csp_packet_t * buffer,
4344

4445
}
4546

46-
csp_packet_t * csp_can_pbuf_new(csp_can_interface_data_t * ifdata, uint32_t id, int * task_woken) {
47+
csp_packet_t * csp_can_pbuf_new(csp_can_interface_data_t * ifdata, uint32_t id, csp_id_t csp_id, int * task_woken) {
4748

4849
csp_can_pbuf_cleanup(ifdata, task_woken);
4950

5051
uint32_t now = (task_woken) ? csp_get_ms_isr() : csp_get_ms();
5152

52-
csp_packet_t * packet = (task_woken) ? csp_buffer_get_always_isr() : csp_buffer_get_always();
53+
csp_packet_t * packet = NULL;
54+
if (csp_iflist_get_by_addr(csp_id.dst) != NULL) {
55+
/* The packet is for us, make sure we don't silently ignore the situation if we can't process it */
56+
packet = (task_woken) ? csp_buffer_get_always_isr() : csp_buffer_get_always();
57+
} else {
58+
/* The packet is not for us, it is ok to drop it if we don't have enough buffers*/
59+
packet = (task_woken) ? csp_buffer_get_isr(0) : csp_buffer_get(0);
60+
}
61+
62+
if (packet == NULL) {
63+
return packet;
64+
}
5365

5466
packet->last_used = now;
5567
packet->cfpid = id;

src/interfaces/csp_if_can_pbuf.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,6 @@ typedef struct {
1111
} csp_can_pbuf_element_t;
1212

1313
void csp_can_pbuf_free(csp_can_interface_data_t * ifdata, csp_packet_t * buffer, int buf_free, int * task_woken);
14-
csp_packet_t * csp_can_pbuf_new(csp_can_interface_data_t * ifdata, uint32_t id, int * task_woken);
14+
csp_packet_t * csp_can_pbuf_new(csp_can_interface_data_t * ifdata, uint32_t id, csp_id_t csp_id, int * task_woken);
1515
csp_packet_t * csp_can_pbuf_find(csp_can_interface_data_t * ifdata, uint32_t id, uint32_t mask, int * task_woken);
1616
void csp_can_pbuf_cleanup(csp_can_interface_data_t * ifdata, int * task_woken);

src/interfaces/csp_if_eth.c

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,9 @@ int csp_eth_rx(csp_iface_t * iface, csp_eth_header_t * eth_frame, uint32_t recei
177177
return CSP_ERR_INVAL;
178178
}
179179

180-
csp_packet_t * packet = csp_eth_pbuf_find(ifdata, packet_id, task_woken);
180+
csp_id_t csp_id = csp_id_extract(eth_frame->frame_begin);
181+
182+
csp_packet_t * packet = csp_eth_pbuf_find(ifdata, packet_id, csp_id, task_woken);
181183

182184
if (packet == NULL) {
183185
iface->drop++;
@@ -188,6 +190,7 @@ int csp_eth_rx(csp_iface_t * iface, csp_eth_header_t * eth_frame, uint32_t recei
188190
if (packet->frame_length == 0) {
189191
/* First segment */
190192
csp_id_setup_rx(packet);
193+
packet->id = csp_id;
191194
packet->frame_length = frame_length;
192195
packet->rx_count = 0;
193196
}
@@ -214,14 +217,9 @@ int csp_eth_rx(csp_iface_t * iface, csp_eth_header_t * eth_frame, uint32_t recei
214217
return CSP_ERR_NONE;
215218
}
216219

217-
csp_eth_pbuf_free(ifdata, packet, false, task_woken);
220+
packet->length = packet->frame_length - csp_id_get_header_size();
218221

219-
if (csp_id_strip(packet) != 0) {
220-
csp_print("eth rx packet discarded due to error in ID field\n");
221-
iface->frame++;
222-
(task_woken) ? csp_buffer_free_isr(packet) : csp_buffer_free(packet);
223-
return CSP_ERR_INVAL;
224-
}
222+
csp_eth_pbuf_free(ifdata, packet, false, task_woken);
225223

226224
/* Record CSP and MAC addresses of source */
227225
csp_eth_arp_set_addr(eth_frame->ether_shost, packet->id.src);

0 commit comments

Comments
 (0)