diff --git a/include/net/if.h b/include/net/if.h index 18833dc66b8..1a56c7e7776 100644 --- a/include/net/if.h +++ b/include/net/if.h @@ -53,7 +53,7 @@ #define IFF_IPv6 (1 << 3) /* Configured for IPv6 packet (vs ARP or IPv4) */ #define IFF_LOOPBACK (1 << 5) /* Is a loopback net */ #define IFF_POINTOPOINT (1 << 6) /* Is point-to-point link */ -#define IFF_NOARP (1 << 7) /* ARP is not required for this packet */ +#define IFF_NOARP (1 << 7) /* ARP is not required for this interface */ #define IFF_NAT (1 << 8) /* NAT is enabled for this interface */ #define IFF_SLAVE (1 << 11) /* Slave of a load balancer. */ #define IFF_MULTICAST (1 << 12) /* Supports multicast. */ diff --git a/net/arp/arp_acd.c b/net/arp/arp_acd.c index 60e591d8306..38f3acf2437 100644 --- a/net/arp/arp_acd.c +++ b/net/arp/arp_acd.c @@ -236,7 +236,7 @@ void arp_acd_update(FAR struct net_driver_s *dev) void arp_acd_setup(FAR struct net_driver_s *dev) { - if (dev->d_acd.need_announce == false) + if (!dev->d_acd.need_announce || IFF_IS_NOARP(dev->d_flags)) { return; } diff --git a/net/arp/arp_input.c b/net/arp/arp_input.c index fdae1478e16..abc4ca91672 100644 --- a/net/arp/arp_input.c +++ b/net/arp/arp_input.c @@ -196,6 +196,15 @@ void arp_input(FAR struct net_driver_s *dev) { FAR uint8_t *buf; + if (IFF_IS_NOARP(dev->d_flags)) + { + /* No arp */ + + ninfo("ARP not supported on %s, no receive!\n", dev->d_ifname); + dev->d_len = 0; + return; + } + if (dev->d_iob != NULL) { buf = dev->d_buf; diff --git a/net/arp/arp_out.c b/net/arp/arp_out.c index ffb33706605..ab7a246a446 100644 --- a/net/arp/arp_out.c +++ b/net/arp/arp_out.c @@ -150,20 +150,6 @@ void arp_out(FAR struct net_driver_s *dev) return; } -#if defined(CONFIG_NET_PKT) || defined(CONFIG_NET_ARP_SEND) - /* Skip sending ARP requests when the frame to be transmitted was - * written into a packet socket. - */ - - if (IFF_IS_NOARP(dev->d_flags)) - { - /* Clear the indication and let the packet continue on its way. */ - - IFF_CLR_NOARP(dev->d_flags); - return; - } -#endif - /* Find the destination IP address in the ARP table and construct * the Ethernet header. If the destination IP address isn't on the * local network, we use the default router's IP address instead. @@ -265,6 +251,15 @@ void arp_out(FAR struct net_driver_s *dev) ret = arp_find(ipaddr, ethaddr.ether_addr_octet, dev, false); if (ret < 0) { + /* No send ARP if the interface forbidden */ + + if (IFF_IS_NOARP(dev->d_flags)) + { + ninfo("ARP not supported on %s, no send!\n", dev->d_ifname); + dev->d_len = 0; + return; + } + ninfo("ARP request for IP %08lx\n", (unsigned long)ipaddr); /* The destination address was not in our ARP table, so we overwrite diff --git a/net/arp/arp_send.c b/net/arp/arp_send.c index 625e04c8692..5643583f8f9 100644 --- a/net/arp/arp_send.c +++ b/net/arp/arp_send.c @@ -134,12 +134,6 @@ static uint16_t arp_send_eventhandler(FAR struct net_driver_s *dev, arp_format(dev, state->snd_ipaddr); - /* Make sure no ARP request overwrites this ARP request. This - * flag will be cleared in arp_out(). - */ - - IFF_SET_NOARP(dev->d_flags); - /* Don't allow any further call backs. */ arp_send_terminate(dev, state, OK); @@ -277,6 +271,14 @@ int arp_send(in_addr_t ipaddr) return OK; } + /* No ARP packet if this device do not support ARP */ + + if (IFF_IS_NOARP(dev->d_flags)) + { + ninfo("ARP not supported on %s, no send!\n", dev->d_ifname); + return OK; + } + /* Allocate resources to receive a callback. This and the following * initialization is performed with the network lock because we don't * want anything to happen until we are ready. diff --git a/net/icmpv6/icmpv6_neighbor.c b/net/icmpv6/icmpv6_neighbor.c index 3d6c602f9de..be8e6827efb 100644 --- a/net/icmpv6/icmpv6_neighbor.c +++ b/net/icmpv6/icmpv6_neighbor.c @@ -259,6 +259,14 @@ int icmpv6_neighbor(FAR struct net_driver_s *dev, #endif } + /* No ARP packet if this device do not support ARP */ + + if (IFF_IS_NOARP(dev->d_flags)) + { + ninfo("ARP not supported on %s, no send!\n", dev->d_ifname); + return -EHOSTUNREACH; + } + /* Allocate resources to receive a callback. This and the following * initialization is performed with the network lock because we don't * want anything to happen until we are ready. diff --git a/net/neighbor/neighbor_ethernet_out.c b/net/neighbor/neighbor_ethernet_out.c index 148ec135706..f3b0870c879 100644 --- a/net/neighbor/neighbor_ethernet_out.c +++ b/net/neighbor/neighbor_ethernet_out.c @@ -100,18 +100,6 @@ void neighbor_ethernet_out(FAR struct net_driver_s *dev) FAR struct ipv6_hdr_s *ip = IPv6BUF; struct neighbor_addr_s laddr; - /* Skip sending Neighbor Solicitations when the frame to be transmitted was - * written into a packet socket. - */ - - if (IFF_IS_NOARP(dev->d_flags)) - { - /* Clear the indication and let the packet continue on its way. */ - - IFF_CLR_NOARP(dev->d_flags); - return; - } - /* Find the destination IPv6 address in the Neighbor Table and construct * the Ethernet header. If the destination IPv6 address isn't on the local * network, we use the default router's IPv6 address instead. @@ -162,6 +150,13 @@ void neighbor_ethernet_out(FAR struct net_driver_s *dev) if (neighbor_lookup(ipaddr, &laddr) < 0) { #ifdef CONFIG_NET_ICMPv6 + /* No ARP packet if this device do not support ARP */ + + if (IFF_IS_NOARP(dev->d_flags)) + { + return; + } + ninfo("IPv6 Neighbor solicitation for IPv6\n"); /* The destination address was not in our Neighbor Table, so we diff --git a/net/netdev/netdev_ioctl.c b/net/netdev/netdev_ioctl.c index e5474842d09..2945744e06d 100644 --- a/net/netdev/netdev_ioctl.c +++ b/net/netdev/netdev_ioctl.c @@ -1026,26 +1026,50 @@ static int netdev_ifr_ioctl(FAR struct socket *psock, int cmd, #endif case SIOCSIFFLAGS: /* Sets the interface flags */ +#ifdef CONFIG_NET_ARP - /* Is this a request to bring the interface up? */ + /* Is this a request to set the IFF_NOARP flag? */ - if ((req->ifr_flags & IFF_UP) != 0) + if (IFF_IS_NOARP(req->ifr_flags) != IFF_IS_NOARP(dev->d_flags)) { - /* Yes.. bring the interface up */ + if (IFF_IS_NOARP(req->ifr_flags)) + { + /* Yes. Set the IFF_NOARP flag */ - ret = netdev_ifup(dev); + IFF_SET_NOARP(dev->d_flags); + } + else + { + /* No. Clear the IFF_NOARP flag */ + + IFF_CLR_NOARP(dev->d_flags); + } + } +#endif + + /* Is this a request to bring the interface up/down? */ + + if (IFF_IS_UP(req->ifr_flags) != IFF_IS_UP(dev->d_flags)) + { + if (IFF_IS_UP(req->ifr_flags)) + { + /* Yes.. bring the interface up */ + + ret = netdev_ifup(dev); #ifdef CONFIG_NET_ARP_ACD - /* having address then start acd */ + /* having address then start acd */ - arp_acd_setup(dev); + arp_acd_setup(dev); #endif /* CONFIG_NET_ARP_ACD */ - } - else - { - /* Yes.. take the interface down */ + } + else + { + /* Yes.. take the interface down */ - ret = netdev_ifdown(dev); + ret = netdev_ifdown(dev); + } } + break; case SIOCGIFFLAGS: /* Gets the interface flags */ diff --git a/net/pkt/pkt_sendmsg_unbuffered.c b/net/pkt/pkt_sendmsg_unbuffered.c index ee70d64eb1e..65d306cccc0 100644 --- a/net/pkt/pkt_sendmsg_unbuffered.c +++ b/net/pkt/pkt_sendmsg_unbuffered.c @@ -138,12 +138,6 @@ static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev, ethhdr->type = pstate->addr->sll_protocol; dev->d_len += NET_LL_HDRLEN(dev); } - - /* Make sure no ARP request overwrites this ARP request. This - * flag will be cleared in arp_out(). - */ - - IFF_SET_NOARP(dev->d_flags); } end_wait: