static int sender_iface(struct net_if *iface, struct net_pkt *pkt) { if (!pkt->frags) { DBG("No data to send!\n"); return -ENODATA; } if (test_started) { struct net_if_test *data = iface->dev->driver_data; DBG("Sending at iface %d %p\n", net_if_get_by_iface(iface), iface); if (net_pkt_iface(pkt) != iface) { DBG("Invalid interface %p, expecting %p\n", net_pkt_iface(pkt), iface); test_failed = true; } if (net_if_get_by_iface(iface) != data->idx) { DBG("Invalid interface %d index, expecting %d\n", data->idx, net_if_get_by_iface(iface)); test_failed = true; } } net_pkt_unref(pkt); k_sem_give(&wait_data); return 0; }
static inline enum net_verdict process_data(struct net_pkt *pkt, bool is_loopback) { int ret; bool locally_routed = false; #if defined(CONFIG_NET_IPV6_FRAGMENT) /* If the packet is routed back to us when we have reassembled * an IPv6 packet, then do not pass it to L2 as the packet does * not have link layer headers in it. */ if (net_pkt_ipv6_fragment_start(pkt)) { locally_routed = true; } #endif /* If there is no data, then drop the packet. */ if (!pkt->frags) { NET_DBG("Corrupted packet (frags %p)", pkt->frags); net_stats_update_processing_error(); return NET_DROP; } if (!is_loopback && !locally_routed) { ret = net_if_recv_data(net_pkt_iface(pkt), pkt); if (ret != NET_CONTINUE) { if (ret == NET_DROP) { NET_DBG("Packet %p discarded by L2", pkt); net_stats_update_processing_error(); } return ret; } } /* IP version and header length. */ switch (NET_IPV6_HDR(pkt)->vtc & 0xf0) { #if defined(CONFIG_NET_IPV6) case 0x60: net_stats_update_ipv6_recv(); net_pkt_set_family(pkt, PF_INET6); return net_ipv6_process_pkt(pkt); #endif #if defined(CONFIG_NET_IPV4) case 0x40: net_stats_update_ipv4_recv(); net_pkt_set_family(pkt, PF_INET); return net_ipv4_process_pkt(pkt); #endif } NET_DBG("Unknown IP family packet (0x%x)", NET_IPV6_HDR(pkt)->vtc & 0xf0); net_stats_update_ip_errors_protoerr(); net_stats_update_ip_errors_vhlerr(); return NET_DROP; }
static int loopback_send(struct device *dev, struct net_pkt *pkt) { struct net_pkt *cloned; int res; ARG_UNUSED(dev); if (!pkt->frags) { LOG_ERR("No data to send"); return -ENODATA; } /* We need to swap the IP addresses because otherwise * the packet will be dropped. */ if (net_pkt_family(pkt) == AF_INET6) { struct in6_addr addr; net_ipaddr_copy(&addr, &NET_IPV6_HDR(pkt)->src); net_ipaddr_copy(&NET_IPV6_HDR(pkt)->src, &NET_IPV6_HDR(pkt)->dst); net_ipaddr_copy(&NET_IPV6_HDR(pkt)->dst, &addr); } else { struct in_addr addr; net_ipaddr_copy(&addr, &NET_IPV4_HDR(pkt)->src); net_ipaddr_copy(&NET_IPV4_HDR(pkt)->src, &NET_IPV4_HDR(pkt)->dst); net_ipaddr_copy(&NET_IPV4_HDR(pkt)->dst, &addr); } /* We should simulate normal driver meaning that if the packet is * properly sent (which is always in this driver), then the packet * must be dropped. This is very much needed for TCP packets where * the packet is reference counted in various stages of sending. */ cloned = net_pkt_clone(pkt, K_MSEC(100)); if (!cloned) { res = -ENOMEM; goto out; } res = net_recv_data(net_pkt_iface(cloned), cloned); if (res < 0) { LOG_ERR("Data receive failed."); } out: /* Let the receiving thread run now */ k_yield(); return res; }
/* Called when data needs to be sent to network */ int net_send_data(struct net_pkt *pkt) { int status; if (!pkt || !pkt->frags) { return -ENODATA; } if (!net_pkt_iface(pkt)) { return -EINVAL; } #if defined(CONFIG_NET_STATISTICS) switch (net_pkt_family(pkt)) { case AF_INET: net_stats_update_ipv4_sent(); break; case AF_INET6: net_stats_update_ipv6_sent(); break; } #endif status = check_ip_addr(pkt); if (status < 0) { return status; } else if (status > 0) { /* Packet is destined back to us so send it directly * to RX processing. */ NET_DBG("Loopback pkt %p back to us", pkt); processing_data(pkt, true); return 0; } if (net_if_send_data(net_pkt_iface(pkt), pkt) == NET_DROP) { return -EIO; } return 0; }
static int eth_send(struct device *dev, struct net_pkt *pkt) { struct eth_context *ctx = dev->driver_data; int count = net_pkt_get_len(pkt); int ret; ret = net_pkt_read(pkt, ctx->send, count); if (ret) { return ret; } update_gptp(net_pkt_iface(pkt), pkt, true); LOG_DBG("Send pkt %p len %d", pkt, count); ret = eth_write_data(ctx->dev_fd, ctx->send, count); if (ret < 0) { LOG_DBG("Cannot send pkt %p (%d)", pkt, ret); } return ret < 0 ? ret : 0; }
struct net_pkt *net_ipv4_create(struct net_context *context, struct net_pkt *pkt, const struct in_addr *src, const struct in_addr *dst) { NET_ASSERT(((struct sockaddr_in_ptr *)&context->local)->sin_addr); if (!src) { src = ((struct sockaddr_in_ptr *)&context->local)->sin_addr; } if (net_is_ipv4_addr_unspecified(src) || net_is_ipv4_addr_mcast(src)) { src = &net_pkt_iface(pkt)->ipv4.unicast[0].address.in_addr; } return net_ipv4_create_raw(pkt, src, dst, net_context_get_iface(context), net_context_get_ip_proto(context)); }