net: Add ll addresses on net_if_send_data

This makes sure ll addresses are properly set before sending reducing the
duplicated code on L2 drivers.

Change-Id: I5330c1d00a344e77555c6f31033ae42af20214bf
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
Luiz Augusto von Dentz 2017-01-31 16:43:43 +02:00 committed by Jukka Rissanen
commit a94f179252
5 changed files with 48 additions and 74 deletions

View file

@ -491,6 +491,11 @@ struct net_buf *net_ipv6_prepare_for_send(struct net_buf *buf)
struct net_if *iface = NULL;
struct net_nbr *nbr;
if (net_nbuf_ll_dst(buf)->addr ||
net_is_ipv6_addr_mcast(&NET_IPV6_BUF(buf)->dst)) {
return buf;
}
if (net_if_ipv6_addr_onlink(&iface,
&NET_IPV6_BUF(buf)->dst)) {
nexthop = &NET_IPV6_BUF(buf)->dst;

View file

@ -87,27 +87,6 @@ static enum net_verdict net_bt_send(struct net_if *iface, struct net_buf *buf)
return NET_DROP;
}
/* TODO: Move ll address check to the stack */
/* If the ll address is not set at all, then we must set
* it here.
*/
if (!net_nbuf_ll_src(buf)->addr) {
net_nbuf_ll_src(buf)->addr = net_nbuf_ll_if(buf)->addr;
net_nbuf_ll_src(buf)->len = net_nbuf_ll_if(buf)->len;
}
/* If the ll dst address is not set check if it is present in the nbr
* cache.
*/
if (!net_nbuf_ll_dst(buf)->addr &&
!net_is_ipv6_addr_mcast(&NET_IPV6_BUF(buf)->dst)) {
buf = net_ipv6_prepare_for_send(buf);
if (!buf) {
return NET_CONTINUE;
}
}
if (!net_6lo_compress(buf, true, NULL)) {
NET_DBG("Packet compression failed");
return NET_DROP;

View file

@ -218,25 +218,17 @@ static enum net_verdict ethernet_send(struct net_if *iface,
NET_DBG("Sending buf %p to iface %p", buf, iface);
#endif
/* If the ll address is not set at all, then we must set
* it here.
/* If the src ll address is multicast or broadcast, then
* what probably happened is that the RX buffer is used
* for sending data back to recipient. We must
* substitute the src address using the real ll address.
*/
if (!net_nbuf_ll_src(buf)->addr) {
if (net_eth_is_addr_broadcast((struct net_eth_addr *)
net_nbuf_ll_src(buf)->addr) ||
net_eth_is_addr_multicast((struct net_eth_addr *)
net_nbuf_ll_src(buf)->addr)) {
net_nbuf_ll_src(buf)->addr = net_nbuf_ll_if(buf)->addr;
net_nbuf_ll_src(buf)->len = net_nbuf_ll_if(buf)->len;
} else {
/* If the src ll address is multicast or broadcast, then
* what probably happened is that the RX buffer is used
* for sending data back to recipient. We must
* substitute the src address using the real ll address.
*/
if (net_eth_is_addr_broadcast((struct net_eth_addr *)
net_nbuf_ll_src(buf)->addr) ||
net_eth_is_addr_multicast((struct net_eth_addr *)
net_nbuf_ll_src(buf)->addr)) {
net_nbuf_ll_src(buf)->addr = net_nbuf_ll_if(buf)->addr;
net_nbuf_ll_src(buf)->len = net_nbuf_ll_if(buf)->len;
}
}
/* If the destination address is not set, then use broadcast
@ -244,34 +236,17 @@ static enum net_verdict ethernet_send(struct net_if *iface,
*/
if (!net_nbuf_ll_dst(buf)->addr) {
#if defined(CONFIG_NET_IPV6)
if (net_nbuf_family(buf) == AF_INET6) {
if (net_is_ipv6_addr_mcast(&NET_IPV6_BUF(buf)->dst)) {
struct net_eth_addr *dst =
&NET_ETH_BUF(buf)->dst;
if (net_nbuf_family(buf) == AF_INET6 &&
net_is_ipv6_addr_mcast(&NET_IPV6_BUF(buf)->dst)) {
struct net_eth_addr *dst = &NET_ETH_BUF(buf)->dst;
memcpy(dst, (uint8_t *)multicast_eth_addr.addr,
sizeof(struct net_eth_addr) - 4);
memcpy((uint8_t *)dst + 2,
(uint8_t *)(&NET_IPV6_BUF(buf)->dst) +
12,
sizeof(struct net_eth_addr) - 2);
memcpy(dst, (uint8_t *)multicast_eth_addr.addr,
sizeof(struct net_eth_addr) - 4);
memcpy((uint8_t *)dst + 2,
(uint8_t *)(&NET_IPV6_BUF(buf)->dst) + 12,
sizeof(struct net_eth_addr) - 2);
net_nbuf_ll_dst(buf)->addr =
(uint8_t *)dst->addr;
} else {
/* Check neighbor cache if it has the
* destination address.
*/
net_nbuf_set_ll_reserve(buf,
sizeof(struct net_eth_hdr));
buf = net_ipv6_prepare_for_send(buf);
if (!buf) {
/* The actual packet will be send later
*/
return NET_CONTINUE;
}
}
net_nbuf_ll_dst(buf)->addr = (uint8_t *)dst->addr;
} else
#endif
{

View file

@ -270,14 +270,6 @@ static enum net_verdict ieee802154_send(struct net_if *iface,
return NET_DROP;
}
if (!net_nbuf_ll_dst(buf)->addr &&
!net_is_ipv6_addr_mcast(&NET_IPV6_BUF(buf)->dst)) {
buf = net_ipv6_prepare_for_send(buf);
if (!buf) {
return NET_CONTINUE;
}
}
/* 6lo is going to compress the ipv6 header, and thus accessing
* packet's ipv6 address won't be possible anymore when creating
* the frame */

View file

@ -144,15 +144,38 @@ enum net_verdict net_if_send_data(struct net_if *iface, struct net_buf *buf)
enum net_verdict verdict;
int status = -EIO;
if (atomic_test_bit(iface->flags, NET_IF_UP)) {
verdict = iface->l2->send(iface, buf);
} else {
if (!atomic_test_bit(iface->flags, NET_IF_UP)) {
/* Drop packet if interface is not up */
NET_WARN("iface %p is down", iface);
verdict = NET_DROP;
status = -ENETDOWN;
goto done;
}
/* If the ll address is not set at all, then we must set
* it here.
*/
if (!net_nbuf_ll_src(buf)->addr) {
net_nbuf_ll_src(buf)->addr = net_nbuf_ll_if(buf)->addr;
net_nbuf_ll_src(buf)->len = net_nbuf_ll_if(buf)->len;
}
#if defined(CONFIG_NET_IPV6)
/* If the ll dst address is not set check if it is present in the nbr
* cache.
*/
if (net_nbuf_family(buf) == AF_INET6) {
buf = net_ipv6_prepare_for_send(buf);
if (!buf) {
verdict = NET_CONTINUE;
goto done;
}
}
#endif
verdict = iface->l2->send(iface, buf);
done:
/* The L2 send() function can return
* NET_OK in which case packet was sent successfully.
* In that case we need to check if any user callbacks need