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