RF24Ethernet - TCP/IP over RF24Network v2.2.6
TMRh20 - Pushing the practical limits of RF24 modules
Loading...
Searching...
No Matches
RF24Ethernet.cpp
Go to the documentation of this file.
1/*
2 RF24Ethernet.cpp - Arduino implementation of a uIP wrapper class.
3 Copyright (c) 2014 tmrh20@gmail.com, github.com/TMRh20
4 Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de>
5 All rights reserved.
6
7 This program is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include "RF24Ethernet.h"
22
23#if USE_LWIP == 2
24
25 #include <zephyr/kernel.h>
26 #include <zephyr/logging/log.h>
27 #include <zephyr/net/net_pkt.h>
28 #include <zephyr/net/net_if.h>
29 #include <zephyr/net/net_core.h>
30 #include <zephyr/net/ethernet.h>
31 #include <zephyr/net/net_ip.h>
32
33IPAddress RF24EthernetClass::_dnsServerAddress;
34
35extern "C" {
36 #include "drivers/net/rf24_netif.h"
37}
38
39extern "C" int rf24_cpp_tx_frame(const uint8_t* data, size_t len)
40{
41 return RF24Ethernet.sendFrame(data, len); // global instance
42}
43
44#endif
45
46#if USE_LWIP == 1
51uint8_t RF24EthernetClass::networkBuffer[MAX_PAYLOAD_SIZE];
52IPAddress RF24EthernetClass::_dnsServerAddress;
53
54/*************************************************************/
55
57{
58 RXQueue->nWrite = 0;
59 RXQueue->nRead = 0;
60}
61
62/*************************************************************/
63
64//Saves RX ethernet frame to the buffer to be processed in the main loop
65void RF24EthernetClass::writeRXQueue(EthQueue* RXQueue, const uint8_t* ethFrame, uint16_t lenEthFrame)
66{
67 if (lenEthFrame > MAX_FRAME_SIZE)
68 {
69 lenEthFrame = MAX_FRAME_SIZE;
70 }
71
72 const uint32_t next = (RXQueue->nWrite + 1) % MAX_RX_QUEUE;
73 if (next == RXQueue->nRead)
74 {
75 return; // Queue is full, keep the unread frame and drop this one
76 }
77
78 memcpy(&RXQueue->data[RXQueue->nWrite], ethFrame, lenEthFrame);
79 RXQueue->len[RXQueue->nWrite] = lenEthFrame;
80 RXQueue->nWrite = next;
81}
82
83/*************************************************************/
84
85pbuf* RF24EthernetClass::readRXQueue(EthQueue* RXQueue)
86{
87 if (RXQueue->nWrite == RXQueue->nRead)
88 return nullptr;
89
90 uint16_t frameLen = RXQueue->len[RXQueue->nRead];
91
92 if (frameLen > MAX_FRAME_SIZE) {
94 return nullptr;
95 }
96
97 pbuf* p = pbuf_alloc(PBUF_IP, frameLen, PBUF_RAM);
98
99 if (p) {
100 if (pbuf_take(p, &RXQueue->data[RXQueue->nRead], frameLen) == ERR_OK) {
101 RXQueue->nRead = (RXQueue->nRead + 1) % MAX_RX_QUEUE;
102 return p;
103 }
104 pbuf_free(p);
105 }
106
107 return nullptr;
108}
109
110/*************************************************************/
111
112bool RF24EthernetClass::isUnicast(const uint8_t frame)
113{
114 return (frame & 0x01) == 0;
115}
116
117/*************************************************************/
118
119static void sendFrameToRadio(const char* buf, uint16_t total_len)
120{
121 if (Ethernet.isUnicast(buf[0]))
122 {
123 MIB2_STATS_NETIF_INC(&Ethernet.myNetif, ifoutucastpkts);
124 }
125 else
126 {
127 MIB2_STATS_NETIF_INC(&Ethernet.myNetif, ifoutnucastpkts);
128 }
129
130 IPAddress gwIP = Ethernet.gatewayIP();
131 int16_t nodeAddress = 0;
132
133 //If not the master node
134 if (Ethernet.mesh.mesh_address != 0) {
135 if (gwIP[3] != buf[19]) { // If not sending to the gateway
136 IPAddress local_ip = Ethernet.localIP();
137 if (local_ip[0] == buf[16] && local_ip[1] == buf[17]) { // If we are local within the nRF24 network
138 //Request an address lookup from the Master node
139 nodeAddress = Ethernet.mesh.getAddress((char)buf[19]); // Do an address lookup
140 if (nodeAddress < 0) {
141 nodeAddress = 0; // If the result is negative, send to master
142 }
143 } // If this address is outside the nRF24 network, it will be send to master (00)
144 }
145 }
146 else {
147 IPAddress local_ip = Ethernet.localIP();
148 if (local_ip[0] == buf[16] && local_ip[1] == buf[17]) { // If within the nRF24 radio network, do a lookup, else send to self (00)
149 nodeAddress = Ethernet.mesh.getAddress((char)buf[19]);
150 if (nodeAddress < 0) {
151 return;
152 }
153 }
154 }
155
156 IF_ETH_DEBUG_L1(Serial.print("Net: Out "); Serial.println(nodeAddress, OCT););
157
158 RF24NetworkHeader headerOut(nodeAddress, EXTERNAL_DATA_TYPE);
159
160 if (total_len && total_len <= MAX_PAYLOAD_SIZE) {
161 RF24Ethernet.network.write(headerOut, buf, total_len);
162 }
163}
164
165/*************************************************************/
166
167err_t netif_output(struct netif* netif, struct pbuf* p)
168{
169 void* context = netif->state;
170 uint16_t total_len = p->tot_len;
171
172 if (p->tot_len > Ethernet.MAX_FRAME_SIZE)
173 {
174 MIB2_STATS_NETIF_INC(netif, ifoutdiscards);
175 return ERR_IF;
176 }
177 if (p->tot_len < Ethernet.MIN_FRAME_SIZE) // Pad to minimum ETH size
178 {
179 total_len = Ethernet.MIN_FRAME_SIZE;
180 }
181
183
184 // TCP keeps the segment and tries again later when it gets ERR_MEM
185 if (queue.nWrite - queue.nRead >= RF24EthernetClass::MAX_TX_QUEUE)
186 {
187 MIB2_STATS_NETIF_INC(netif, ifoutdiscards);
188 return ERR_MEM;
189 }
190
191 const uint32_t slot = queue.nWrite % RF24EthernetClass::MAX_TX_QUEUE;
192 pbuf_copy_partial(p, queue.data[slot], p->tot_len, 0);
193 memset(&queue.data[slot][p->tot_len], 0, total_len - p->tot_len);
194 queue.len[slot] = total_len;
196 queue.nWrite = queue.nWrite + 1;
197
198 LINK_STATS_INC(link.xmit);
199 MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p->tot_len);
200
201 return ERR_OK;
202}
203
204/*************************************************************/
205
207{
208 if (TXQueue.nRead == TXQueue.nWrite)
209 {
210 return;
211 }
212 ETHERNET_TX_BARRIER(); // See the complete frame that nWrite published
213
214 const uint32_t slot = TXQueue.nRead % MAX_TX_QUEUE;
215 sendFrameToRadio(reinterpret_cast<const char*>(TXQueue.data[slot]), TXQueue.len[slot]);
217 TXQueue.nRead = TXQueue.nRead + 1;
218}
219
220/*************************************************************/
221
222err_t tun_netif_output(struct netif* netif, struct pbuf* p, const ip4_addr_t* ipaddr)
223{
224 /* Since this is a TUN/L3 interface, we skip ARP (etharp_output).
225 We simply call the linkoutput function to send the raw IP packet. */
226 return netif->linkoutput(netif, p);
227}
228
229/*************************************************************/
230
231err_t netif_init(struct netif* myNetif)
232{
233
234 myNetif->name[0] = 'e';
235 myNetif->name[1] = '0';
236 myNetif->linkoutput = netif_output;
237 myNetif->output = tun_netif_output;
238 myNetif->mtu = MAX_PAYLOAD_SIZE; //ETHERNET_MTU;
239 myNetif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_IGMP | NETIF_FLAG_MLD6 | NETIF_FLAG_LINK_UP;
240 myNetif->hostname = "TmrNet";
241 MIB2_INIT_NETIF(&Ethernet.myNetif, snmp_ifType_ppp, Ethernet.NetIF_Speed_BPS);
242 //SMEMCPY(myNetif->hwaddr, &Ethernet.MacAddr, sizeof(myNetif->hwaddr));
243 myNetif->hwaddr_len = 0; //sizeof(netif->hwaddr);
244 Ethernet.initRXQueue(&Ethernet.RXQueue);
245 Ethernet.TXQueue.nRead = 0;
246 Ethernet.TXQueue.nWrite = 0;
247 netif_set_link_up(myNetif);
248 return ERR_OK;
249}
250
251#endif
252
253/*************************************************************/
254#if !defined NRF52_RADIO_LIBRARY
255 #if defined(RF24_TAP)
256RF24EthernetClass::RF24EthernetClass(RF24& _radio, RF24Network& _network) : radio(_radio), network(_network) // fn_uip_cb(NULL)
257{
258 #if USE_LWIP == 1
261 #endif
262 #if USE_LWIP == 2
263 isInitialized = false;
264 #endif
265}
266
267 #else // Using RF24Mesh
268RF24EthernetClass::RF24EthernetClass(RF24& _radio, RF24Network& _network, RF24Mesh& _mesh) : radio(_radio), network(_network), mesh(_mesh) // fn_uip_cb(NULL)
269{
270 #if USE_LWIP == 1
273 #endif
274 #if USE_LWIP == 2
275 isInitialized = false;
276 #endif
277}
278 #endif
279
280#else
281 #if defined(RF24_TAP)
282RF24EthernetClass::RF24EthernetClass(nrf_to_nrf& _radio, RF52Network& _network) : radio(_radio), network(_network) // fn_uip_cb(NULL)
283{
284 #if USE_LWIP == 1
287 #endif
288 #if USE_LWIP == 2
289 isInitialized = false;
290 #endif
291}
292
293 #else // Using RF24Mesh
294RF24EthernetClass::RF24EthernetClass(nrf_to_nrf& _radio, RF52Network& _network, RF52Mesh& _mesh) : radio(_radio), network(_network), mesh(_mesh) // fn_uip_cb(NULL)
295{
296 #if USE_LWIP == 1
297 RF24Client::gState[0] = new RF24Client::ConnectState;
298 RF24Client::gState[1] = new RF24Client::ConnectState;
299 #endif
300 #if USE_LWIP == 2
301 isInitialized = false;
302 #endif
303}
304 #endif
305#endif
306/*************************************************************/
307
309{
310 Ethernet.tick();
311}
312
313/*************************************************************/
314
316{
317 // Kept for backwards compatibility only
318}
319
320/*******************************************************/
321
322void RF24EthernetClass::setMac(uint16_t address)
323{
324 if (!network.multicastRelay) { // Radio has not been started yet
325 radio.begin();
326 }
327
328 const uint8_t mac[6] = {0x52, 0x46, 0x32, 0x34, (uint8_t)address, (uint8_t)(address >> 8)};
329 // printf("MAC: %o %d\n", address, mac[0]);
330
331#if defined(RF24_TAP)
332 uip_seteth_addr(mac);
333 network.multicastRelay = 1;
334#else
335 if (mac[0] == 1) {
336 // Dummy operation to prevent warnings if TAP not defined
337 };
338#endif
339 RF24_Channel = RF24_Channel ? RF24_Channel : 97;
340 network.begin(RF24_Channel, address);
341}
342
343/*******************************************************/
344
345void RF24EthernetClass::setChannel(uint8_t channel)
346{
347 RF24_Channel = channel;
348 if (network.multicastRelay) { // Radio has not been started yet
349 radio.setChannel(RF24_Channel);
350 }
351}
352
353/*******************************************************/
354
355void RF24EthernetClass::begin(IPAddress ip)
356{
357 IPAddress dns = {8, 8, 8, 8};
358 begin(ip, dns);
359}
360
361/*******************************************************/
362
363void RF24EthernetClass::begin(IPAddress ip, IPAddress dns)
364{
365 IPAddress gateway = ip;
366 gateway[3] = 1;
367 begin(ip, dns, gateway);
368}
369
370/*******************************************************/
371
372void RF24EthernetClass::begin(IPAddress ip, IPAddress dns, IPAddress gateway)
373{
374 IPAddress subnet(255, 255, 255, 0);
375 begin(ip, dns, gateway, subnet);
376}
377
378/*******************************************************/
379
380void RF24EthernetClass::begin(IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet)
381{
382 configure(ip, dns, gateway, subnet);
383}
384
385/*******************************************************/
386
387void RF24EthernetClass::configure(IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet)
388{
389#if !defined(RF24_TAP) // Using RF24Mesh
390 mesh.setNodeID(ip[3]);
391#endif
392
393#if USE_LWIP < 1
394 uip_buf = (uint8_t*)&network.frag_ptr->message_buffer[0];
395
396 uip_ipaddr_t ipaddr;
397 uip_ip_addr(ipaddr, ip);
398 uip_sethostaddr(ipaddr);
399 uip_ip_addr(ipaddr, gateway);
400 uip_setdraddr(ipaddr);
401 uip_ip_addr(ipaddr, subnet);
402 uip_setnetmask(ipaddr);
403 _dnsServerAddress = dns;
404
405 timer_set(&this->periodic_timer, CLOCK_SECOND / UIP_TIMER_DIVISOR);
406
407 #if defined(RF24_TAP)
408 timer_set(&this->arp_timer, CLOCK_SECOND * 2);
409 #endif
410
411 uip_init();
412 #if defined(RF24_TAP)
413 uip_arp_init();
414 #endif
415#elif USE_LWIP == 1
416
418 // Allocate data for a single client
419 RF24Client::incomingData[RF24Client::activeState] = (char*)malloc(INCOMING_DATA_SIZE);
420 RF24Client::clientConnectionTimeout = 0;
421 RF24Client::serverConnectionTimeout = 30000;
422
423 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING && defined ESP32
424 wifi_mode_t mode;
425 esp_err_t err = esp_wifi_get_mode(&mode);
426 if (err == ESP_OK) {
427 useCoreLocking = true;
428 }
429 else {
430 useCoreLocking = false;
431 }
432 #elif defined RF24ETHERNET_CORE_REQUIRES_LOCKING
433 useCoreLocking = true;
434 #endif
435
436 ip4_addr_t myIp, myMask, myGateway;
437 IP4_ADDR(&myIp, ip[0], ip[1], ip[2], ip[3]);
438 IP4_ADDR(&myMask, subnet[0], subnet[1], subnet[2], subnet[3]);
439 IP4_ADDR(&myGateway, gateway[0], gateway[1], gateway[2], gateway[3]);
440 _dnsServerAddress = dns;
441
442 void* context = nullptr;
443 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
444 if (useCoreLocking) {
445 ETHERNET_APPLY_LOCK();
446 }
447 #endif
448 netif_add(&Ethernet.myNetif, &myIp, &myMask, &myGateway, context, netif_init, ip_input);
449 netif_set_default(&Ethernet.myNetif);
450 netif_set_up(&Ethernet.myNetif);
451 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
452 if (useCoreLocking) {
453 ETHERNET_REMOVE_LOCK();
454 }
455 #endif
456
457#elif USE_LWIP == 2
458
459 struct net_if* iface = rf24_netif_get_iface();
460 if (!iface) {
461 IF_RF24ETHERNET_DEBUG_CLIENT(printk("NET: rf24 iface null\n"));
462 return;
463 }
464
465 struct in_addr my_ip, netmask, gw;
466
467 my_ip.s_addr = (uint32_t)ip;
468 netmask.s_addr = (uint32_t)subnet;
469 gw.s_addr = (uint32_t)gateway;
470
471 //net_addr_pton(AF_INET, (uint32_t)ip, &my_ip);
472 //net_addr_pton(AF_INET, (uint32_t)subnet, &netmask);
473 //net_addr_pton(AF_INET, (uint32_t)gateway, &gw);
474
475 net_if_ipv4_addr_add(iface, &my_ip, NET_ADDR_MANUAL, 0);
476 net_if_ipv4_set_netmask_by_addr(iface, &my_ip, &netmask);
477 net_if_ipv4_set_gw(iface, &gw);
478
479 int ret = net_if_up(iface);
480 if (ret < 0 && ret != -EALREADY) {
481 IF_RF24ETHERNET_DEBUG_CLIENT(printk("NET: net_if_up failed (%d)\n", ret));
482 return;
483 }
484 IF_RF24ETHERNET_DEBUG_CLIENT(printk("NET: iface up\n"));
485
486 ethLocalIP = ip;
487 //printk("%s\n",localIP().toString().c_str());
488 _dnsServerAddress = dns;
489 isInitialized = true;
490 RF24Client::serverConnectionTimeout = 30000;
491
492#endif
493}
494
495/*******************************************************/
496
498{
499#if USE_LWIP < 1
500 uip_ipaddr_t ipaddr;
501 uip_ip_addr(ipaddr, gwIP);
502 uip_setdraddr(ipaddr);
503#elif USE_LWIP == 1
504 ip4_addr_t new_gw;
505 IP4_ADDR(&new_gw, gwIP[0], gwIP[1], gwIP[2], gwIP[3]);
506 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
507 if (useCoreLocking) {
508 ETHERNET_APPLY_LOCK();
509 }
510 #endif
511 netif_set_gw(&Ethernet.myNetif, &new_gw);
512 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
513 if (useCoreLocking) {
514 ETHERNET_REMOVE_LOCK();
515 }
516 #endif
517#elif USE_LWIP == 2
518
519 struct net_if* iface = rf24_netif_get_iface();
520 if (iface == NULL) {
521 IF_RF24ETHERNET_DEBUG_CLIENT(printk("NET: Set GW: no default iface\n"));
522 return;
523 }
524 struct in_addr gate;
525 gate.s_addr = gwIP;
526 net_if_ipv4_set_gw(iface, &gate);
527
528#endif
529}
530
531/*******************************************************/
532
533void RF24EthernetClass::listen(uint16_t port)
534{
535#if USE_LWIP < 1
536 uip_listen(HTONS(port));
537#elif USE_LWIP == 1
538
539 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
540 if (useCoreLocking) {
541 ETHERNET_APPLY_LOCK();
542 }
543 #endif
544 RF24Client::myPcb = tcp_new();
545 tcp_err(RF24Client::myPcb, RF24Client::error_callback);
546
547 err_t err = tcp_bind(RF24Client::myPcb, IP_ADDR_ANY, port);
548 if (err != ERR_OK) {
549 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println("Server: Unable to bind to port"););
550 }
551
552 RF24Client::gState[0]->connected = false;
553 RF24Client::gState[0]->result = 0;
554
555 RF24Client::myPcb = tcp_listen(RF24Client::myPcb);
556
557 tcp_arg(RF24Client::myPcb, &RF24Client::gState[0]);
558 tcp_accept(RF24Client::myPcb, RF24Client::accept);
559
560 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
561 if (useCoreLocking) {
562 ETHERNET_REMOVE_LOCK();
563 }
564 #endif
565#else
566
567#endif
568}
569
570/*******************************************************/
571
573{
574#if USE_LWIP < 1
575 uip_ipaddr_t a;
576 uip_gethostaddr(a);
577 return ip_addr_uip(a);
578#elif USE_LWIP == 1
579 if (netif_is_up(&myNetif)) {
580 // Get the IP address structure
581 const ip4_addr_t* ip_addr = netif_ip4_addr(&myNetif);
582 return (IPAddress(ip_addr->addr));
583 }
584#elif USE_LWIP == 2
585
586 return ethLocalIP;
587
588#endif
589 return IPAddress {0, 0, 0, 0};
590}
591
592/*******************************************************/
593
595{
596#if USE_LWIP < 1
597 uip_ipaddr_t a;
598 uip_getnetmask(a);
599 return ip_addr_uip(a);
600#elif USE_LWIP == 1
601 if (netif_is_up(&myNetif)) {
602 // Get the IP address structure
603 const ip4_addr_t* ip_addr = netif_ip4_netmask(&myNetif);
604 return (IPAddress(ip_addr->addr));
605 }
606 return IPAddress {0, 0, 0, 0};
607#elif USE_LWIP == 2
608
609 struct net_if* iface = rf24_netif_get_iface();
610 if (iface == NULL) {
611 IF_RF24ETHERNET_DEBUG_CLIENT(printk("NET: Set GW: no default iface\n"));
612 return IPAddress {0, 0, 0, 0};
613 }
614
615 struct in_addr my_ip;
616 my_ip.s_addr = localIP();
617 struct in_addr mask = net_if_ipv4_get_netmask_by_addr(iface, &my_ip);
618 return mask.s_addr;
619
620#endif
621}
622
623/*******************************************************/
624
626{
627#if USE_LWIP < 1
628 uip_ipaddr_t a;
629 uip_getdraddr(a);
630 return ip_addr_uip(a);
631#elif USE_LWIP == 1
632 if (netif_is_up(&myNetif)) {
633 // Get the IP address structure
634 const ip4_addr_t* ip_addr = netif_ip4_gw(&myNetif);
635 return (IPAddress(ip_addr->addr));
636 }
637 return IPAddress {0, 0, 0, 0};
638#elif USE_LWIP == 2
639 struct net_if* iface = rf24_netif_get_iface();
640 if (iface == NULL) {
641 IF_RF24ETHERNET_DEBUG_CLIENT(printk("NET: Set GW: no default iface\n"));
642 return IPAddress {0, 0, 0, 0};
643 }
644
645 return net_if_ipv4_get_gw(iface).s_addr;
646
647#endif
648}
649
650/*******************************************************/
651
653{
654 return _dnsServerAddress;
655}
656
657/*******************************************************/
658#if USE_LWIP == 1
659//Should be call inside PHY RX Ethernet IRQ
660void RF24EthernetClass::EthRX_Handler(const uint8_t* ethFrame, const uint16_t lenEthFrame)
661{
662 LINK_STATS_INC(link.recv);
663 MIB2_STATS_NETIF_ADD(&Ethernet.myNetif, ifinoctets, lenEthFrame);
664 if (Ethernet.isUnicast(ethFrame[0]))
665 {
666 MIB2_STATS_NETIF_INC(&Ethernet.myNetif, ifinucastpkts);
667 }
668 else
669 {
670 MIB2_STATS_NETIF_INC(&Ethernet.myNetif, ifinnucastpkts);
671 }
672
673 writeRXQueue(&RXQueue, ethFrame, lenEthFrame);
674}
675
676#endif
677
678/*******************************************************/
679
680void RF24EthernetClass::tick()
681{
682
683#if defined __ZEPHYR__
684 k_msleep(1);
685#elif defined ARDUINO_ARCH_ESP32
686 const TickType_t xDelay = pdMS_TO_TICKS(1);
687 vTaskDelay(xDelay);
688#elif defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_ARCH_NRF52) || defined ARDUINO_ARCH_RP2350 || defined ARDUINO_NRF54L15
689 yield();
690#endif
691
692#if USE_LWIP < 1
693 uint8_t result = RF24Ethernet.mesh.update();
694
695 if (Ethernet.mesh.mesh_address == 0) {
696 Ethernet.mesh.DHCP();
697 }
698
699 if (result == EXTERNAL_DATA_TYPE) {
700 if (RF24Ethernet.network.frag_ptr->message_size <= UIP_BUFSIZE && RF24Ethernet.network.frag_ptr->message_size >= 28) {
701 uip_len = RF24Ethernet.network.frag_ptr->message_size;
702 }
703 }
704 else if (result == NETWORK_CORRUPTION) {
706 }
707
708 #if !defined(RF24_TAP)
709 if (uip_len > 0) {
710 uip_input();
711 if (uip_len > 0) {
712 network_send();
713 }
714 }
715 else if (timer_expired(&Ethernet.periodic_timer)) {
716 timer_reset(&Ethernet.periodic_timer);
717 for (int i = 0; i < UIP_CONNS; i++) {
718 uip_periodic(i);
719 /* If the above function invocation resulted in data that
720 should be sent out on the network, the global variable
721 uip_len is set to a value > 0. */
722 if (uip_len > 0) {
723 network_send();
724 }
725 }
726 }
727 #else // defined (RF24_TAP)
728 if (uip_len > 0) {
729 if (BUF->type == htons(UIP_ETHTYPE_IP)) {
730 uip_arp_ipin();
731 uip_input();
732 /* If the above function invocation resulted in data that
733 should be sent out on the network, the global variable
734 uip_len is set to a value > 0. */
735 if (uip_len > 0) {
736 uip_arp_out();
737 network_send();
738 }
739 }
740 else if (BUF->type == htons(UIP_ETHTYPE_ARP)) {
741 uip_arp_arpin();
742 /* If the above function invocation resulted in data that
743 should be sent out on the network, the global variable
744 uip_len is set to a value > 0. */
745 if (uip_len > 0) {
746 network_send();
747 }
748 }
749 }
750 else if (timer_expired(&Ethernet.periodic_timer)) {
751 timer_reset(&Ethernet.periodic_timer);
752 for (int i = 0; i < UIP_CONNS; i++) {
753 uip_periodic(i);
754 /* If the above function invocation resulted in data that
755 should be sent out on the network, the global variable
756 uip_len is set to a value > 0. */
757 if (uip_len > 0) {
758 uip_arp_out();
759 network_send();
760 }
761 }
762 #endif // defined (RF24_TAP)
763 #if UIP_UDP
764 for (int i = 0; i < UIP_UDP_CONNS; i++) {
765 uip_udp_periodic(i);
766 /* If the above function invocation resulted in data that
767 should be sent out on the network, the global variable
768 uip_len is set to a value > 0. */
769 if (uip_len > 0) {
770 // uip_arp_out();
771 // network_send();
772 RF24UDP::_send((uip_udp_userdata_t*)(uip_udp_conns[i].appstate));
773 }
774 }
775 #endif /* UIP_UDP */
776 #if defined(RF24_TAP)
777 /* Call the ARP timer function every 10 seconds. */
778
779 if (timer_expired(&Ethernet.arp_timer)) {
780 timer_reset(&Ethernet.arp_timer);
781 uip_arp_timer();
782 }
783}
784 #endif // RF24_TAP
785
786#elif USE_LWIP == 1 // Using LWIP
787
788 uint8_t result = RF24Ethernet.mesh.update();
789
790 if (Ethernet.mesh.mesh_address == 0) {
791 Ethernet.mesh.DHCP();
792 }
793
794 if (result == EXTERNAL_DATA_TYPE) {
795 uint16_t len = RF24Ethernet.network.frag_ptr->message_size;
796 if (len > 28) {
797 memcpy(networkBuffer, RF24Ethernet.network.frag_ptr->message_buffer, len);
798 Ethernet.EthRX_Handler(networkBuffer, len);
799 IF_ETH_DEBUG_L1(Serial.println("Net: In"););
800 }
801 }
802
803 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
804 if (useCoreLocking) {
805 ETHERNET_APPLY_LOCK();
806 }
807 #endif
808 sys_check_timeouts();
809
810 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
811 if (useCoreLocking) {
812 ETHERNET_REMOVE_LOCK();
813 }
814 #endif
815
816 pbuf* p = readRXQueue(&RXQueue);
817 if (p != nullptr)
818 {
819
820 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
821 if (useCoreLocking) {
822 ETHERNET_APPLY_LOCK();
823 }
824 #endif
825 if (myNetif.input(p, &myNetif) != ERR_OK)
826 {
827 LWIP_DEBUGF(NETIF_DEBUG, ("IP input error\r\n"));
828 if (p != nullptr) {
829 pbuf_free(p);
830 p = NULL;
831 }
832 }
833
834 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
835 if (useCoreLocking) {
836 ETHERNET_REMOVE_LOCK();
837 }
838 #endif
839 }
841
842#elif USE_LWIP == 2
843
844 uint8_t result = RF24Ethernet.mesh.update();
845
846 if (Ethernet.mesh.mesh_address == 0) {
847 Ethernet.mesh.DHCP();
848 }
849
850 if (result == EXTERNAL_DATA_TYPE) {
851 const uint16_t len = RF24Ethernet.network.frag_ptr->message_size;
852 if (len == 0 || len > MAX_PAYLOAD_SIZE) {
853 return;
854 }
855 uint8_t* buf = RF24Ethernet.network.frag_ptr->message_buffer;
856 rf24_netif_deliver_frame(RF24Ethernet.network.frag_ptr->message_buffer, RF24Ethernet.network.frag_ptr->message_size);
857 }
858
859#endif
860}
861
862/*******************************************************/
863
864void RF24EthernetClass::network_send()
865{
866
867#if USE_LWIP < 1
868 IPAddress gwIP = Ethernet.gatewayIP();
869 int16_t nodeAddress = 0;
870
871 //If not the master node
872 if (Ethernet.mesh.mesh_address != 0) {
873 if (gwIP[3] != uip_buf[19]) { // If not sending to the gateway
874 IPAddress local_ip = Ethernet.localIP();
875 if (local_ip[0] == uip_buf[16] && local_ip[1] == uip_buf[17]) { // If we are local within the nRF24 network
876 //Request an address lookup from the Master node
877 nodeAddress = Ethernet.mesh.getAddress((char)uip_buf[19]); // Do an address lookup
878 if (nodeAddress < 0) {
879 nodeAddress = 0; // If the result is negative, send to master
880 }
881 } // If this address is outside the nRF24 network, it will be send to master (00)
882 }
883 }
884 else {
885 IPAddress local_ip = Ethernet.localIP();
886 if (local_ip[0] == uip_buf[16] && local_ip[1] == uip_buf[17]) { // If within the nRF24 radio network, do a lookup, else send to self (00)
887 nodeAddress = Ethernet.mesh.getAddress((char)uip_buf[19]);
888 if (nodeAddress < 0) {
889 return;
890 }
891 }
892 }
893 RF24NetworkHeader headerOut(nodeAddress, EXTERNAL_DATA_TYPE);
894
895 #if defined ETH_DEBUG_L1 || defined ETH_DEBUG_L2
896 bool ok = RF24Ethernet.network.write(headerOut, uip_buf, uip_len);
897 if (!ok) {
898 Serial.println();
899 Serial.print(millis());
900 Serial.println(F(" *** RF24Ethernet Network Write Fail ***"));
901 }
902 #else
903 RF24Ethernet.network.write(headerOut, uip_buf, uip_len);
904 #endif
905
906 #if defined ETH_DEBUG_L2
907 if (ok) {
908 Serial.println();
909 Serial.print(millis());
910 Serial.println(F(" RF24Ethernet Network Write OK"));
911 }
912 #endif
913#else
914
915#endif
916}
917
918/*******************************************************/
919#if USE_LWIP == 2
920int RF24EthernetClass::sendFrame(const uint8_t* data, size_t len)
921{
922 IF_RF24ETHERNET_DEBUG_CLIENT(printk("Net out\n"));
923
924 if (!data || !len || !isInitialized) {
925 return -EINVAL;
926 }
927
928 IPAddress gwIP = Ethernet.gatewayIP();
929
930 int16_t nodeAddress = 0;
931 const uint8_t* buf = data;
932 //If not the master node
933 if (Ethernet.mesh.mesh_address != 0) {
934 if (gwIP[3] != buf[19]) { // If not sending to the gateway
935 IPAddress local_ip = Ethernet.localIP();
936 if (local_ip[0] == buf[16] && local_ip[1] == buf[17]) { // If we are local within the nRF24 network
937 //Request an address lookup from the Master node
938 nodeAddress = Ethernet.mesh.getAddress((char)buf[19]); // Do an address lookup
939 if (nodeAddress < 0) {
940 nodeAddress = 0; // If the result is negative, send to master
941 }
942 } // If this address is outside the nRF24 network, it will be send to master (00)
943 }
944 }
945 else {
946 IPAddress local_ip = Ethernet.localIP();
947
948 if (local_ip[0] == buf[16] && local_ip[1] == buf[17]) { // If within the nRF24 radio network, do a lookup, else send to self (00)
949 nodeAddress = Ethernet.mesh.getAddress((char)buf[19]);
950 if (nodeAddress < 0) {
951 return 0;
952 }
953 }
954 }
955
956 memcpy(outputBuffer, data, len);
957 RF24NetworkHeader headerOut(nodeAddress, EXTERNAL_DATA_TYPE);
958 bool ok = RF24Ethernet.network.write(headerOut, outputBuffer, len);
959 IF_RF24ETHERNET_DEBUG_CLIENT(printk("Net out ok:%d len=%zu\n", ok, len));
960 return 0; //ok ? 0 : -EIO;
961}
962#endif
963/*******************************************************/
#define HTONS
#define ETHERNET_TX_BARRIER()
volatile err_t result
Definition RF24Client.h:4
#define INCOMING_DATA_SIZE
Definition RF24Client.h:85
err_t tun_netif_output(struct netif *netif, struct pbuf *p, const ip4_addr_t *ipaddr)
err_t netif_init(struct netif *myNetif)
static void sendFrameToRadio(const char *buf, uint16_t total_len)
err_t netif_output(struct netif *netif, struct pbuf *p)
#define BUF
#define uip_ip_addr(addr, ip)
#define ip_addr_uip(a)
#define uip_seteth_addr(eaddr)
RF24EthernetClass RF24Ethernet
static void error_callback(void *arg, err_t err)
static ConnectState * gState[2]
Definition RF24Client.h:224
static bool activeState
Definition RF24Client.h:239
uint32_t networkCorruption
static EthQueue RXQueue
void setMac(uint16_t address)
void setChannel(uint8_t channel)
static void sendQueuedFrame()
static void writeRXQueue(EthQueue *RXQueue, const uint8_t *ethFrame, uint16_t lenEthFrame)
static void initRXQueue(EthQueue *RXQueue)
IPAddress dnsServerIP()
void listen(uint16_t port)
static EthTxQueue TXQueue
IPAddress subnetMask()
void set_gateway(IPAddress gwIP)
static constexpr unsigned MAX_FRAME_SIZE
static bool isUnicast(const uint8_t frame)
RF24Network & network
static netif myNetif
static constexpr unsigned MAX_RX_QUEUE
static constexpr unsigned MAX_TX_QUEUE
void begin(IP_ADDR myIP, IP_ADDR subnet)
static bool useCoreLocking
IPAddress gatewayIP()
#define Ethernet
#define IF_RF24ETHERNET_DEBUG_CLIENT(x)
#define IF_ETH_DEBUG_L1(x)
#define UIP_TIMER_DIVISOR
Adjust the rate at which the IP stack performs periodic processing.
Definition uip-conf.h:127
uint16_t len[MAX_RX_QUEUE]
uint16_t len[MAX_TX_QUEUE]