@@ -16,6 +16,7 @@ LOG_MODULE_REGISTER(net_arp, CONFIG_NET_ARP_LOG_LEVEL);
16
16
#include <zephyr/net/net_pkt.h>
17
17
#include <zephyr/net/net_if.h>
18
18
#include <zephyr/net/net_stats.h>
19
+ #include <zephyr/net/net_mgmt.h>
19
20
20
21
#include "arp.h"
21
22
#include "net_private.h"
@@ -34,6 +35,12 @@ static struct k_work_delayable arp_request_timer;
34
35
35
36
static struct k_mutex arp_mutex ;
36
37
38
+ #if defined(CONFIG_NET_ARP_GRATUITOUS_TRANSMISSION )
39
+ static struct net_mgmt_event_callback iface_event_cb ;
40
+ static struct net_mgmt_event_callback ipv4_event_cb ;
41
+ static struct k_work_delayable arp_gratuitous_work ;
42
+ #endif /* defined(CONFIG_NET_ARP_GRATUITOUS_TRANSMISSION) */
43
+
37
44
static void arp_entry_cleanup (struct arp_entry * entry , bool pending )
38
45
{
39
46
NET_DBG ("entry %p" , entry );
@@ -466,6 +473,141 @@ static void arp_gratuitous(struct net_if *iface,
466
473
}
467
474
}
468
475
476
+ #if defined(CONFIG_NET_ARP_GRATUITOUS_TRANSMISSION )
477
+ static void arp_gratuitous_send (struct net_if * iface ,
478
+ struct in_addr * ipaddr )
479
+ {
480
+ struct net_arp_hdr * hdr ;
481
+ struct net_pkt * pkt ;
482
+
483
+ pkt = net_pkt_alloc_with_buffer (iface , sizeof (struct net_arp_hdr ),
484
+ AF_UNSPEC , 0 , NET_BUF_TIMEOUT );
485
+ if (!pkt ) {
486
+ return ;
487
+ }
488
+
489
+ net_buf_add (pkt -> buffer , sizeof (struct net_arp_hdr ));
490
+ net_pkt_set_vlan_tag (pkt , net_eth_get_vlan_tag (iface ));
491
+
492
+ hdr = NET_ARP_HDR (pkt );
493
+
494
+ hdr -> hwtype = htons (NET_ARP_HTYPE_ETH );
495
+ hdr -> protocol = htons (NET_ETH_PTYPE_IP );
496
+ hdr -> hwlen = sizeof (struct net_eth_addr );
497
+ hdr -> protolen = sizeof (struct in_addr );
498
+ hdr -> opcode = htons (NET_ARP_REQUEST );
499
+
500
+ memcpy (& hdr -> dst_hwaddr .addr , net_eth_broadcast_addr (),
501
+ sizeof (struct net_eth_addr ));
502
+ memcpy (& hdr -> src_hwaddr .addr , net_if_get_link_addr (iface )-> addr ,
503
+ sizeof (struct net_eth_addr ));
504
+
505
+ net_ipv4_addr_copy_raw (hdr -> dst_ipaddr , (uint8_t * )ipaddr );
506
+ net_ipv4_addr_copy_raw (hdr -> src_ipaddr , (uint8_t * )ipaddr );
507
+
508
+ net_pkt_lladdr_src (pkt )-> addr = net_if_get_link_addr (iface )-> addr ;
509
+ net_pkt_lladdr_src (pkt )-> len = sizeof (struct net_eth_addr );
510
+
511
+ net_pkt_lladdr_dst (pkt )-> addr = (uint8_t * )net_eth_broadcast_addr ();
512
+ net_pkt_lladdr_dst (pkt )-> len = sizeof (struct net_eth_addr );
513
+
514
+ NET_DBG ("Sending gratuitous ARP pkt %p" , pkt );
515
+
516
+ if (net_if_send_data (iface , pkt ) == NET_DROP ) {
517
+ net_pkt_unref (pkt );
518
+ }
519
+ }
520
+
521
+ static void notify_all_ipv4_addr (struct net_if * iface )
522
+ {
523
+ struct net_if_ipv4 * ipv4 = iface -> config .ip .ipv4 ;
524
+ int i ;
525
+
526
+ if (!ipv4 ) {
527
+ return ;
528
+ }
529
+
530
+ for (i = 0 ; i < NET_IF_MAX_IPV4_ADDR ; i ++ ) {
531
+ if (ipv4 -> unicast [i ].ipv4 .is_used &&
532
+ ipv4 -> unicast [i ].ipv4 .address .family == AF_INET &&
533
+ ipv4 -> unicast [i ].ipv4 .addr_state == NET_ADDR_PREFERRED ) {
534
+ arp_gratuitous_send (iface ,
535
+ & ipv4 -> unicast [i ].ipv4 .address .in_addr );
536
+ }
537
+ }
538
+ }
539
+
540
+ static void iface_event_handler (struct net_mgmt_event_callback * cb ,
541
+ uint32_t mgmt_event , struct net_if * iface )
542
+ {
543
+ ARG_UNUSED (cb );
544
+
545
+ if (!(net_if_l2 (iface ) == & NET_L2_GET_NAME (ETHERNET ) ||
546
+ net_eth_is_vlan_interface (iface ))) {
547
+ return ;
548
+ }
549
+
550
+ if (mgmt_event != NET_EVENT_IF_UP ) {
551
+ return ;
552
+ }
553
+
554
+ notify_all_ipv4_addr (iface );
555
+ }
556
+
557
+ static void ipv4_event_handler (struct net_mgmt_event_callback * cb ,
558
+ uint32_t mgmt_event , struct net_if * iface )
559
+ {
560
+ struct in_addr * ipaddr ;
561
+
562
+ if (!(net_if_l2 (iface ) == & NET_L2_GET_NAME (ETHERNET ) ||
563
+ net_eth_is_vlan_interface (iface ))) {
564
+ return ;
565
+ }
566
+
567
+ if (!net_if_is_up (iface )) {
568
+ return ;
569
+ }
570
+
571
+ if (mgmt_event != NET_EVENT_IPV4_ADDR_ADD ) {
572
+ return ;
573
+ }
574
+
575
+ if (cb -> info_length != sizeof (struct in_addr )) {
576
+ return ;
577
+ }
578
+
579
+ ipaddr = (struct in_addr * )cb -> info ;
580
+
581
+ arp_gratuitous_send (iface , ipaddr );
582
+ }
583
+
584
+ static void iface_cb (struct net_if * iface , void * user_data )
585
+ {
586
+ ARG_UNUSED (user_data );
587
+
588
+ if (!(net_if_l2 (iface ) == & NET_L2_GET_NAME (ETHERNET ) ||
589
+ net_eth_is_vlan_interface (iface ))) {
590
+ return ;
591
+ }
592
+
593
+ if (!net_if_is_up (iface )) {
594
+ return ;
595
+ }
596
+
597
+ notify_all_ipv4_addr (iface );
598
+ }
599
+
600
+ static void arp_gratuitous_work_handler (struct k_work * work )
601
+ {
602
+ ARG_UNUSED (work );
603
+
604
+ net_if_foreach (iface_cb , NULL );
605
+
606
+ k_work_reschedule (& arp_gratuitous_work ,
607
+ K_SECONDS (CONFIG_NET_ARP_GRATUITOUS_INTERVAL ));
608
+ }
609
+ #endif /* defined(CONFIG_NET_ARP_GRATUITOUS_TRANSMISSION) */
610
+
469
611
void net_arp_update (struct net_if * iface ,
470
612
struct in_addr * src ,
471
613
struct net_eth_addr * hwaddr ,
@@ -837,4 +979,19 @@ void net_arp_init(void)
837
979
k_mutex_init (& arp_mutex );
838
980
839
981
arp_cache_initialized = true;
982
+
983
+ #if defined(CONFIG_NET_ARP_GRATUITOUS_TRANSMISSION )
984
+ net_mgmt_init_event_callback (& iface_event_cb , iface_event_handler ,
985
+ NET_EVENT_IF_UP );
986
+ net_mgmt_init_event_callback (& ipv4_event_cb , ipv4_event_handler ,
987
+ NET_EVENT_IPV4_ADDR_ADD );
988
+
989
+ net_mgmt_add_event_callback (& iface_event_cb );
990
+ net_mgmt_add_event_callback (& ipv4_event_cb );
991
+
992
+ k_work_init_delayable (& arp_gratuitous_work ,
993
+ arp_gratuitous_work_handler );
994
+ k_work_reschedule (& arp_gratuitous_work ,
995
+ K_SECONDS (CONFIG_NET_ARP_GRATUITOUS_INTERVAL ));
996
+ #endif /* defined(CONFIG_NET_ARP_GRATUITOUS_TRANSMISSION) */
840
997
}
0 commit comments