net: udp: Remove NET_UDP_HDR() macro and direct access to net_buf

Remove NET_UDP_HDR() macro as we cannot safely access UDP header
via it if the network packet header spans over multiple net_buf
fragments.

Fixed also the UDP unit tests so that they pass correctly.

Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
This commit is contained in:
Jukka Rissanen 2017-06-30 17:46:01 +03:00
commit 3604c391e6
34 changed files with 1068 additions and 114 deletions

View file

@ -321,12 +321,6 @@ static inline u8_t *net_pkt_ip_data(struct net_pkt *pkt)
return pkt->frags->data;
}
static inline u8_t *net_pkt_udp_data(struct net_pkt *pkt)
{
return &pkt->frags->data[net_pkt_ip_hdr_len(pkt) +
net_pkt_ipv6_ext_len(pkt)];
}
static inline u8_t *net_pkt_tcp_data(struct net_pkt *pkt)
{
return &pkt->frags->data[net_pkt_ip_hdr_len(pkt) +
@ -408,7 +402,6 @@ static inline void net_pkt_set_ieee802154_rssi(struct net_pkt *pkt,
#define NET_IPV6_HDR(pkt) ((struct net_ipv6_hdr *)net_pkt_ip_data(pkt))
#define NET_IPV4_HDR(pkt) ((struct net_ipv4_hdr *)net_pkt_ip_data(pkt))
#define NET_UDP_HDR(pkt) ((struct net_udp_hdr *)(net_pkt_udp_data(pkt)))
#define NET_TCP_HDR(pkt) ((struct net_tcp_hdr *)(net_pkt_tcp_data(pkt)))
static inline void net_pkt_set_src_ipv6_addr(struct net_pkt *pkt)

70
include/net/udp.h Normal file
View file

@ -0,0 +1,70 @@
/** @file
@brief UDP utility functions
*/
/*
* Copyright (c) 2017 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __UDP_H
#define __UDP_H
#include <zephyr/types.h>
#include <net/net_core.h>
#include <net/net_ip.h>
#include <net/net_pkt.h>
#ifdef __cplusplus
extern "C" {
#endif
#if defined(CONFIG_NET_UDP)
/**
* @brief Get UDP packet header data from net_pkt.
*
* @details The values in the returned header are in network byte order.
* Note that you must access the UDP header values by the returned pointer,
* the hdr parameter is just a placeholder for the header data and it might
* not contain anything if header can fit properly in the first fragment in
* the network packet.
*
* @param pkt Network packet
* @param hdr Where to place the header if it does not fit in first fragment
* of the network packet.
*
* @return Return pointer to header or NULL if something went wrong.
*/
struct net_udp_hdr *net_udp_get_hdr(struct net_pkt *pkt,
struct net_udp_hdr *hdr);
/**
* @brief Set UDP packet header data in net_pkt.
*
* @details The values in the header must be in network byte order.
* This function is normally called after a call to net_udp_get_hdr().
* The hdr parameter value should be the same that is returned by function
* net_udp_get_hdr() call. Note that if the UDP header fits in first net_pkt
* fragment, then this function will not do anything as your hdr parameter
* was pointing directly to net_pkt.
*
* @param pkt Network packet
* @param hdr Header data pointer that was returned by net_udp_get_hdr().
*
* @return Return pointer to header or NULL if something went wrong.
*/
struct net_udp_hdr *net_udp_set_hdr(struct net_pkt *pkt,
struct net_udp_hdr *hdr);
#else
#define net_udp_get_hdr(pkt, frag) NULL
#define net_udp_set_hdr(pkt, frag) NULL
#endif /* CONFIG_NET_UDP */
#ifdef __cplusplus
}
#endif
#endif /* __UDP_H */

View file

@ -15,6 +15,7 @@
#include <net/net_if.h>
#include <net/net_core.h>
#include <net/net_context.h>
#include <net/udp.h>
#include <bluetooth/bluetooth.h>
#include <gatt/ipss.h>
@ -205,10 +206,18 @@ static inline void set_dst_addr(sa_family_t family,
struct net_pkt *pkt,
struct sockaddr *dst_addr)
{
struct net_udp_hdr hdr, *udp_hdr;
udp_hdr = net_udp_get_hdr(pkt, &hdr);
if (!udp_hdr) {
printk("Invalid UDP data\n");
return;
}
net_ipaddr_copy(&net_sin6(dst_addr)->sin6_addr,
&NET_IPV6_HDR(pkt)->src);
net_sin6(dst_addr)->sin6_family = AF_INET6;
net_sin6(dst_addr)->sin6_port = NET_UDP_HDR(pkt)->src_port;
net_sin6(dst_addr)->sin6_port = udp_hdr->src_port;
}
static void udp_received(struct net_context *context,

View file

@ -9,6 +9,7 @@
#include <net/net_context.h>
#include <net/net_pkt.h>
#include <net/net_if.h>
#include <net/udp.h>
#include <string.h>
#include <errno.h>
#include <misc/printk.h>
@ -20,9 +21,17 @@ static const socklen_t addrlen = sizeof(struct sockaddr_in6);
static void set_client_address(struct sockaddr *addr, struct net_pkt *rx_pkt)
{
struct net_udp_hdr hdr, *udp_hdr;
udp_hdr = net_udp_get_hdr(rx_pkt, &hdr);
if (!udp_hdr) {
printk("Invalid UDP data\n");
return;
}
net_ipaddr_copy(&net_sin6(addr)->sin6_addr, &NET_IPV6_HDR(rx_pkt)->src);
net_sin6(addr)->sin6_family = AF_INET6;
net_sin6(addr)->sin6_port = NET_UDP_HDR(rx_pkt)->src_port;
net_sin6(addr)->sin6_port = udp_hdr->src_port;
}
static void udp_received(struct net_context *context,

View file

@ -75,6 +75,7 @@ struct net_pkt *build_reply_pkt(const char *name,
reply_pkt = net_app_get_net_pkt(ctx, net_pkt_family(pkt), K_FOREVER);
NET_ASSERT(reply_pkt);
NET_ASSERT(net_pkt_family(reply_pkt) == net_pkt_family(pkt));
recv_len = net_pkt_get_len(pkt);

View file

@ -19,6 +19,7 @@
#include <net/net_pkt.h>
#include <net/net_core.h>
#include <net/net_context.h>
#include <net/udp.h>
#include <net/net_app.h>
@ -51,12 +52,19 @@ static inline void set_dst_addr(sa_family_t family,
struct net_pkt *pkt,
struct sockaddr *dst_addr)
{
struct net_udp_hdr hdr, *udp_hdr;
udp_hdr = net_udp_get_hdr(pkt, &hdr);
if (!udp_hdr) {
return;
}
#if defined(CONFIG_NET_IPV6)
if (family == AF_INET6) {
net_ipaddr_copy(&net_sin6(dst_addr)->sin6_addr,
&NET_IPV6_HDR(pkt)->src);
net_sin6(dst_addr)->sin6_family = AF_INET6;
net_sin6(dst_addr)->sin6_port = NET_UDP_HDR(pkt)->src_port;
net_sin6(dst_addr)->sin6_port = udp_hdr->src_port;
}
#endif /* CONFIG_NET_IPV6) */
@ -65,7 +73,7 @@ static inline void set_dst_addr(sa_family_t family,
net_ipaddr_copy(&net_sin(dst_addr)->sin_addr,
&NET_IPV4_HDR(pkt)->src);
net_sin(dst_addr)->sin_family = AF_INET;
net_sin(dst_addr)->sin_port = NET_UDP_HDR(pkt)->src_port;
net_sin(dst_addr)->sin_port = udp_hdr->src_port;
}
#endif /* CONFIG_NET_IPV6) */
}

View file

@ -20,6 +20,7 @@
#include <net/net_ip.h>
#include <net/net_pkt.h>
#include <net/net_context.h>
#include <net/udp.h>
#include <net_private.h>
@ -412,10 +413,19 @@ static void udp_receive(struct net_context *context,
{
struct zoap_packet request;
struct sockaddr_in6 from;
struct net_udp_hdr hdr, *udp_hdr;
int r, header_len;
net_ipaddr_copy(&from.sin6_addr, &NET_IPV6_HDR(pkt)->src);
from.sin6_port = NET_UDP_HDR(pkt)->src_port;
udp_hdr = net_udp_get_hdr(pkt, &hdr);
if (!udp_hdr) {
printk("Invalid UDP data received\n");
net_pkt_unref(pkt);
return;
}
from.sin6_port = udp_hdr->src_port;
from.sin6_family = AF_INET6;
/*

View file

@ -9,6 +9,7 @@
#include <net/net_context.h>
#include <net/net_pkt.h>
#include <net/net_if.h>
#include <net/udp.h>
#include <string.h>
#include <errno.h>
#include <misc/printk.h>
@ -21,9 +22,17 @@ static const socklen_t addrlen = sizeof(struct sockaddr_in6);
static void set_client_address(struct sockaddr *addr, struct net_pkt *rx_buf)
{
struct net_udp_hdr hdr, *udp_hdr;
udp_hdr = net_udp_get_hdr(rx_buf, &hdr);
if (!udp_hdr) {
printk("Invalid UDP data\n");
return;
}
net_ipaddr_copy(&net_sin6(addr)->sin6_addr, &NET_IPV6_HDR(rx_buf)->src);
net_sin6(addr)->sin6_family = AF_INET6;
net_sin6(addr)->sin6_port = NET_UDP_HDR(rx_buf)->src_port;
net_sin6(addr)->sin6_port = udp_hdr->src_port;
}
#else
@ -31,9 +40,17 @@ static const socklen_t addrlen = sizeof(struct sockaddr_in);
static void set_client_address(struct sockaddr *addr, struct net_pkt *rx_buf)
{
struct net_udp_hdr hdr, *udp_hdr;
udp_hdr = net_udp_get_hdr(rx_buf, &hdr);
if (!udp_hdr) {
printk("Invalid UDP data\n");
return;
}
net_ipaddr_copy(&net_sin(addr)->sin_addr, &NET_IPV4_HDR(rx_buf)->src);
net_sin(addr)->sin_family = AF_INET;
net_sin(addr)->sin_port = NET_UDP_HDR(rx_buf)->src_port;
net_sin(addr)->sin_port = udp_hdr->src_port;
}
#endif

View file

@ -2,7 +2,7 @@ CONFIG_INIT_STACKS=y
CONFIG_NETWORKING=y
CONFIG_NET_TCP=y
CONFIG_NET_UDP=n
CONFIG_NET_UDP=y
CONFIG_NET_ARP=y
CONFIG_NET_L2_BLUETOOTH=y
CONFIG_NET_L2_BLUETOOTH_SEC_LEVEL=1

View file

@ -14,6 +14,7 @@
#include <net/net_pkt.h>
#include <net/net_mgmt.h>
#include <net/net_ip.h>
#include <net/udp.h>
#include <net/zoap.h>
#if defined(CONFIG_NET_L2_BLUETOOTH)
@ -76,6 +77,7 @@ static void udp_receive(struct net_context *context,
struct zoap_reply *reply;
struct zoap_packet response;
struct sockaddr_in6 from;
struct net_udp_hdr hdr, *udp_hdr;
int header_len, r;
/*
@ -98,7 +100,14 @@ static void udp_receive(struct net_context *context,
}
net_ipaddr_copy(&from.sin6_addr, &NET_IPV6_HDR(pkt)->src);
from.sin6_port = NET_UDP_HDR(pkt)->src_port;
udp_hdr = net_udp_get_hdr(pkt, &hdr);
if (!udp_hdr) {
printk("Invalid UDP data received\n");
return;
}
from.sin6_port = udp_hdr->src_port;
reply = zoap_response_received(&response,
(const struct sockaddr *) &from,

View file

@ -20,6 +20,7 @@
#include <net/buf.h>
#include <net/net_pkt.h>
#include <net/net_ip.h>
#include <net/udp.h>
#include <net/zoap.h>
#include <net/zoap_link_format.h>
@ -1115,10 +1116,19 @@ static void udp_receive(struct net_context *context,
struct zoap_packet request;
struct zoap_pending *pending;
struct sockaddr_in6 from;
struct net_udp_hdr hdr, *udp_hdr;
int r, header_len;
net_ipaddr_copy(&from.sin6_addr, &NET_IPV6_HDR(pkt)->src);
from.sin6_port = NET_UDP_HDR(pkt)->src_port;
udp_hdr = net_udp_get_hdr(pkt, &hdr);
if (!udp_hdr) {
printk("Invalid UDP data received\n");
net_pkt_unref(pkt);
return;
}
from.sin6_port = udp_hdr->src_port;
from.sin6_family = AF_INET6;
/*

View file

@ -7,6 +7,7 @@
#include <zephyr.h>
#include <net/net_pkt.h>
#include <net/udp.h>
#include "zperf_session.h"
@ -21,6 +22,7 @@ struct session *get_session(struct net_pkt *pkt, enum session_proto proto)
struct session *free = NULL;
struct in6_addr ipv6 = { };
struct in_addr ipv4 = { };
struct net_udp_hdr hdr, *udp_hdr;
int i = 0;
u16_t port;
@ -34,8 +36,14 @@ struct session *get_session(struct net_pkt *pkt, enum session_proto proto)
return NULL;
}
udp_hdr = net_udp_get_hdr(pkt, &hdr);
if (!udp_hdr) {
printk("Invalid UDP data\n");
return NULL;
}
/* Get tuple of the remote connection */
port = NET_UDP_HDR(pkt)->src_port;
port = udp_hdr->src_port;
if (net_pkt_family(pkt) == AF_INET6) {
net_ipaddr_copy(&ipv6, &NET_IPV6_HDR(pkt)->src);

View file

@ -12,6 +12,7 @@
#include <net/net_core.h>
#include <net/net_pkt.h>
#include <net/udp.h>
#include "zperf.h"
#include "zperf_internal.h"
@ -40,12 +41,20 @@ static inline void set_dst_addr(sa_family_t family,
struct net_pkt *pkt,
struct sockaddr *dst_addr)
{
struct net_udp_hdr hdr, *udp_hdr;
udp_hdr = net_udp_get_hdr(pkt, &hdr);
if (!udp_hdr) {
printk(TAG "Invalid UDP data\n");
return;
}
#if defined(CONFIG_NET_IPV6)
if (family == AF_INET6) {
net_ipaddr_copy(&net_sin6(dst_addr)->sin6_addr,
&NET_IPV6_HDR(pkt)->src);
net_sin6(dst_addr)->sin6_family = AF_INET6;
net_sin6(dst_addr)->sin6_port = NET_UDP_HDR(pkt)->src_port;
net_sin6(dst_addr)->sin6_port = udp_hdr->src_port;
}
#endif /* CONFIG_NET_IPV6 */
@ -54,7 +63,7 @@ static inline void set_dst_addr(sa_family_t family,
net_ipaddr_copy(&net_sin(dst_addr)->sin_addr,
&NET_IPV4_HDR(pkt)->src);
net_sin(dst_addr)->sin_family = AF_INET;
net_sin(dst_addr)->sin_port = NET_UDP_HDR(pkt)->src_port;
net_sin(dst_addr)->sin_port = udp_hdr->src_port;
}
#endif /* CONFIG_NET_IPV4 */
}

View file

@ -22,14 +22,21 @@ static u8_t sample_packet[PACKET_SIZE_MAX];
static inline void zperf_upload_decode_stat(struct net_pkt *pkt,
struct zperf_results *results)
{
struct net_buf *frag = pkt->frags;
struct net_buf *frag;
struct zperf_server_hdr hdr;
u16_t offset;
u16_t pos;
offset = net_pkt_udp_data(pkt) - net_pkt_ip_data(pkt);
offset += sizeof(struct net_udp_hdr) +
sizeof(struct zperf_udp_datagram);
frag = net_frag_get_pos(pkt,
net_pkt_ip_hdr_len(pkt) +
net_pkt_ipv6_ext_len(pkt) +
sizeof(struct net_udp_hdr) +
sizeof(struct zperf_udp_datagram),
&offset);
if (!frag) {
printk(TAG "ERROR! Network packet too short\n");
return;
}
/* Decode stat */
if (!pkt) {

View file

@ -17,6 +17,7 @@
#include <net/net_core.h>
#include <net/net_if.h>
#include <net/net_stats.h>
#include <net/udp.h>
#include "net_private.h"
#include "6lo.h"
@ -684,7 +685,6 @@ static inline bool compress_IPHC_header(struct net_pkt *pkt,
#endif
struct net_ipv6_hdr *ipv6 = NET_IPV6_HDR(pkt);
u8_t offset = 0;
struct net_udp_hdr *udp;
struct net_buf *frag;
u8_t compressed;
@ -752,11 +752,19 @@ static inline bool compress_IPHC_header(struct net_pkt *pkt,
}
/* UDP header compression */
udp = NET_UDP_HDR(pkt);
IPHC[offset] = NET_6LO_NHC_UDP_BARE;
offset = compress_nh_udp(udp, frag, offset);
if (IS_ENABLED(CONFIG_NET_UDP)) {
struct net_udp_hdr hdr, *udp;
compressed += NET_UDPH_LEN;
udp = net_udp_get_hdr(pkt, &hdr);
NET_ASSERT(udp);
IPHC[offset] = NET_6LO_NHC_UDP_BARE;
offset = compress_nh_udp(udp, frag, offset);
compressed += NET_UDPH_LEN;
net_udp_set_hdr(pkt, udp);
}
end:
net_buf_add(frag, offset);

View file

@ -17,6 +17,7 @@ obj-$(CONFIG_NET_RPL) += rpl.o
obj-$(CONFIG_NET_RPL_MRHOF) += rpl-mrhof.o
obj-$(CONFIG_NET_RPL_OF0) += rpl-of0.o
obj-$(CONFIG_NET_MGMT_EVENT) += net_mgmt.o
obj-$(CONFIG_NET_UDP) += udp.o
obj-$(CONFIG_NET_TCP) += tcp.o
obj-$(CONFIG_NET_SHELL) += net_shell.o
obj-$(CONFIG_NET_STATISTICS) += net_stats.o

View file

@ -18,10 +18,12 @@
#include <net/net_core.h>
#include <net/net_pkt.h>
#include <net/udp.h>
#include "net_private.h"
#include "icmpv6.h"
#include "icmpv4.h"
#include "udp_internal.h"
#include "connection.h"
#include "net_stats.h"
@ -44,12 +46,6 @@
static struct net_conn conns[CONFIG_NET_MAX_CONN];
/* This is only used for getting source and destination ports. Because
* both TCP and UDP header have these in the same location, we can check
* them both using the UDP struct.
*/
#define NET_CONN_HDR(pkt) ((struct net_udp_hdr *)(net_pkt_udp_data(pkt)))
#if defined(CONFIG_NET_CONN_CACHE)
/* Cache the connection so that we do not have to go
@ -213,13 +209,20 @@ static inline s32_t get_conn(enum net_ip_protocol proto,
struct net_pkt *pkt,
u32_t *cache_value)
{
struct net_udp_hdr hdr, *udp_hdr;
udp_hdr = net_udp_get_hdr(pkt, &hdr);
if (!udp_hdr) {
return NET_DROP;
}
#if defined(CONFIG_NET_IPV4)
if (family == AF_INET) {
return check_hash(proto, family,
&NET_IPV4_HDR(pkt)->src,
&NET_IPV4_HDR(pkt)->dst,
NET_UDP_HDR(pkt)->src_port,
NET_UDP_HDR(pkt)->dst_port,
udp_hdr->src_port,
udp_hdr->dst_port,
cache_value);
}
#endif
@ -229,8 +232,8 @@ static inline s32_t get_conn(enum net_ip_protocol proto,
return check_hash(proto, family,
&NET_IPV6_HDR(pkt)->src,
&NET_IPV6_HDR(pkt)->dst,
NET_UDP_HDR(pkt)->src_port,
NET_UDP_HDR(pkt)->dst_port,
udp_hdr->src_port,
udp_hdr->dst_port,
cache_value);
}
#endif
@ -289,14 +292,20 @@ static inline enum net_verdict cache_check(enum net_ip_protocol proto,
if (conn_cache[*pos].idx >= 0) {
/* Connection is in the cache */
struct net_conn *conn;
struct net_udp_hdr hdr, *udp_hdr;
udp_hdr = net_udp_get_hdr(pkt, &hdr);
if (!udp_hdr) {
return NET_CONTINUE;
}
conn = &conns[conn_cache[*pos].idx];
NET_DBG("Cache %s listener for pkt %p src port %u "
"dst port %u family %d cache[%d] 0x%x",
net_proto2str(proto), pkt,
ntohs(NET_CONN_HDR(pkt)->src_port),
ntohs(NET_CONN_HDR(pkt)->dst_port),
ntohs(udp_hdr->src_port),
ntohs(udp_hdr->dst_port),
net_pkt_family(pkt), *pos,
conn_cache[*pos].value);
@ -766,6 +775,7 @@ static inline void send_icmp_error(struct net_pkt *pkt)
enum net_verdict net_conn_input(enum net_ip_protocol proto, struct net_pkt *pkt)
{
struct net_udp_hdr hdr, *udp_hdr;
int i, best_match = -1;
s16_t best_rank = -1;
u16_t chksum;
@ -781,17 +791,26 @@ enum net_verdict net_conn_input(enum net_ip_protocol proto, struct net_pkt *pkt)
}
#endif
/* This is only used for getting source and destination ports.
* Because both TCP and UDP header have these in the same
* location, we can check them both using the UDP struct.
*/
udp_hdr = net_udp_get_hdr(pkt, &hdr);
if (!udp_hdr) {
return NET_DROP;
}
if (proto == IPPROTO_TCP) {
chksum = NET_TCP_HDR(pkt)->chksum;
} else {
chksum = NET_UDP_HDR(pkt)->chksum;
chksum = udp_hdr->chksum;
}
if (IS_ENABLED(CONFIG_NET_DEBUG_CONN)) {
NET_DBG("Check %s listener for pkt %p src port %u dst port %u "
"family %d chksum 0x%04x", net_proto2str(proto), pkt,
ntohs(NET_CONN_HDR(pkt)->src_port),
ntohs(NET_CONN_HDR(pkt)->dst_port),
ntohs(udp_hdr->src_port),
ntohs(udp_hdr->dst_port),
net_pkt_family(pkt), ntohs(chksum));
}
@ -806,14 +825,14 @@ enum net_verdict net_conn_input(enum net_ip_protocol proto, struct net_pkt *pkt)
if (net_sin(&conns[i].remote_addr)->sin_port) {
if (net_sin(&conns[i].remote_addr)->sin_port !=
NET_CONN_HDR(pkt)->src_port) {
udp_hdr->src_port) {
continue;
}
}
if (net_sin(&conns[i].local_addr)->sin_port) {
if (net_sin(&conns[i].local_addr)->sin_port !=
NET_CONN_HDR(pkt)->dst_port) {
udp_hdr->dst_port) {
continue;
}
}
@ -855,16 +874,14 @@ enum net_verdict net_conn_input(enum net_ip_protocol proto, struct net_pkt *pkt)
proto == IPPROTO_UDP) {
u16_t chksum_calc;
NET_UDP_HDR(pkt)->chksum = 0;
chksum_calc = ~net_calc_chksum_udp(pkt);
net_udp_set_chksum(pkt, pkt->frags);
chksum_calc = net_udp_get_chksum(pkt, pkt->frags);
if (chksum != chksum_calc) {
net_stats_update_udp_chkerr();
goto drop;
}
NET_UDP_HDR(pkt)->chksum = chksum;
} else if (IS_ENABLED(CONFIG_NET_TCP_CHECKSUM) &&
proto == IPPROTO_TCP) {
u16_t chksum_calc;
@ -876,8 +893,6 @@ enum net_verdict net_conn_input(enum net_ip_protocol proto, struct net_pkt *pkt)
net_stats_update_tcp_seg_chkerr();
goto drop;
}
NET_TCP_HDR(pkt)->chksum = chksum;
}
#if defined(CONFIG_NET_CONN_CACHE)

View file

@ -23,7 +23,8 @@
#include <net/net_if.h>
#include "net_private.h"
#include "udp.h"
#include <net/udp.h>
#include "udp_internal.h"
#include <net/dhcpv4.h>
struct dhcp_msg {
@ -250,11 +251,13 @@ static inline bool add_sname(struct net_pkt *pkt)
static void setup_header(struct net_pkt *pkt, const struct in_addr *server_addr)
{
struct net_ipv4_hdr *ipv4;
struct net_udp_hdr *udp;
struct net_udp_hdr hdr, *udp;
u16_t len;
ipv4 = NET_IPV4_HDR(pkt);
udp = NET_UDP_HDR(pkt);
udp = net_udp_get_hdr(pkt, &hdr);
NET_ASSERT(udp && udp != &hdr);
len = net_pkt_get_len(pkt);
@ -277,6 +280,8 @@ static void setup_header(struct net_pkt *pkt, const struct in_addr *server_addr)
udp->len = htons(len);
udp->chksum = 0;
udp->chksum = ~net_calc_chksum_udp(pkt);
net_udp_set_hdr(pkt, udp);
}
/* Prepare initial DHCPv4 message and add options as per message type */

View file

@ -22,6 +22,7 @@
#include "connection.h"
#include "net_stats.h"
#include "icmpv4.h"
#include "udp_internal.h"
#include "ipv4.h"
struct net_pkt *net_ipv4_create_raw(struct net_pkt *pkt,
@ -97,8 +98,7 @@ int net_ipv4_finalize_raw(struct net_pkt *pkt, u8_t next_header)
#if defined(CONFIG_NET_UDP)
if (next_header == IPPROTO_UDP) {
NET_UDP_HDR(pkt)->chksum = 0;
NET_UDP_HDR(pkt)->chksum = ~net_calc_chksum_udp(pkt);
net_udp_set_chksum(pkt, pkt->frags);
}
#endif
#if defined(CONFIG_NET_TCP)

View file

@ -27,6 +27,7 @@
#include "net_private.h"
#include "connection.h"
#include "icmpv6.h"
#include "udp_internal.h"
#include "ipv6.h"
#include "nbr.h"
#include "6lo.h"
@ -699,8 +700,7 @@ int net_ipv6_finalize_raw(struct net_pkt *pkt, u8_t next_header)
#if defined(CONFIG_NET_UDP)
if (next_header == IPPROTO_UDP) {
NET_UDP_HDR(pkt)->chksum = 0;
NET_UDP_HDR(pkt)->chksum = ~net_calc_chksum_udp(pkt);
net_udp_set_chksum(pkt, pkt->frags);
} else
#endif

View file

@ -18,6 +18,7 @@
#include <net/net_pkt.h>
#include <net/net_if.h>
#include <net/net_stats.h>
#include <net/udp.h>
#include "ieee802154_fragment.h"
@ -320,7 +321,15 @@ static void update_protocol_header_lengths(struct net_pkt *pkt, u16_t size)
NET_IPV6_HDR(pkt)->len[1] = (u8_t) (size - NET_IPV6H_LEN);
if (NET_IPV6_HDR(pkt)->nexthdr == IPPROTO_UDP) {
NET_UDP_HDR(pkt)->len = htons(size - NET_IPV6H_LEN);
struct net_udp_hdr hdr, *udp_hdr;
udp_hdr = net_udp_get_hdr(pkt, &hdr);
NET_ASSERT(udp_hdr);
udp_hdr->len = htons(size - NET_IPV6H_LEN);
net_udp_set_hdr(pkt, udp_hdr);
}
}

View file

@ -30,7 +30,7 @@
#include "ipv6.h"
#include "ipv4.h"
#include "udp.h"
#include "udp_internal.h"
#include "tcp.h"
#include "net_stats.h"
@ -1850,13 +1850,23 @@ static int create_udp_packet(struct net_context *context,
struct net_pkt **out_pkt)
{
int r = 0;
struct net_pkt *tmp;
#if defined(CONFIG_NET_IPV6)
if (net_pkt_family(pkt) == AF_INET6) {
struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)dst_addr;
pkt = net_ipv6_create(context, pkt, NULL, &addr6->sin6_addr);
pkt = net_udp_append(context, pkt, ntohs(addr6->sin6_port));
tmp = net_udp_insert(context, pkt,
net_pkt_ip_hdr_len(pkt) +
net_pkt_ipv6_ext_len(pkt),
addr6->sin6_port);
if (!tmp) {
return -ENOMEM;
}
pkt = tmp;
r = net_ipv6_finalize(context, pkt);
} else
#endif /* CONFIG_NET_IPV6 */
@ -1866,7 +1876,14 @@ static int create_udp_packet(struct net_context *context,
struct sockaddr_in *addr4 = (struct sockaddr_in *)dst_addr;
pkt = net_ipv4_create(context, pkt, NULL, &addr4->sin_addr);
pkt = net_udp_append(context, pkt, ntohs(addr4->sin_port));
tmp = net_udp_insert(context, pkt, net_pkt_ip_hdr_len(pkt),
addr4->sin_port);
if (!tmp) {
return -ENOMEM;
}
pkt = tmp;
r = net_ipv4_finalize(context, pkt);
} else
#endif /* CONFIG_NET_IPV4 */
@ -2048,28 +2065,33 @@ int net_context_sendto(struct net_pkt *pkt,
static void set_appdata_values(struct net_pkt *pkt, enum net_ip_protocol proto)
{
size_t total_len = net_pkt_get_len(pkt);
u16_t proto_len = 0;
struct net_buf *frag;
u16_t offset;
#if defined(CONFIG_NET_UDP)
if (proto == IPPROTO_UDP) {
net_pkt_set_appdata(pkt, net_pkt_udp_data(pkt) +
sizeof(struct net_udp_hdr));
} else
proto_len = sizeof(struct net_udp_hdr);
}
#endif /* CONFIG_NET_UDP */
#if defined(CONFIG_NET_TCP)
if (proto == IPPROTO_TCP) {
net_pkt_set_appdata(pkt, net_pkt_udp_data(pkt) +
tcp_hdr_len(pkt));
} else
net_pkt_set_appdata(pkt, net_pkt_tcp_data(pkt) +
tcp_hdr_len(pkt));
}
#endif /* CONFIG_NET_TCP */
{
net_pkt_set_appdata(pkt, net_pkt_ip_data(pkt) +
net_pkt_ip_hdr_len(pkt));
frag = net_frag_get_pos(pkt, net_pkt_ip_hdr_len(pkt) +
net_pkt_ipv6_ext_len(pkt) +
proto_len,
&offset);
if (frag) {
net_pkt_set_appdata(pkt, frag->data + offset);
}
net_pkt_set_appdatalen(pkt, total_len -
(net_pkt_appdata(pkt) -
net_pkt_ip_data(pkt)));
net_pkt_set_appdatalen(pkt, total_len - net_pkt_ip_hdr_len(pkt) -
net_pkt_ipv6_ext_len(pkt) - proto_len);
NET_ASSERT_INFO(net_pkt_appdatalen(pkt) < total_len,
"Wrong appdatalen %u, total %zu",

View file

@ -46,7 +46,7 @@
#include "rpl.h"
#include "connection.h"
#include "udp.h"
#include "udp_internal.h"
#include "tcp.h"
#include "net_stats.h"

View file

@ -1720,6 +1720,32 @@ u8_t *net_pkt_icmp_opt_data(struct net_pkt *pkt, size_t opt_len)
return frag->data + offset;
}
struct net_udp_hdr *net_pkt_udp_data(struct net_pkt *pkt)
{
struct net_buf *frag;
u16_t offset;
frag = net_frag_get_pos(pkt,
net_pkt_ip_hdr_len(pkt) +
net_pkt_ipv6_ext_len(pkt),
&offset);
if (!frag) {
/* We tried to read past the end of the data */
NET_ASSERT_INFO(frag,
"IP hdr %d ext len %d offset %d pos %d "
"total %zd",
net_pkt_ip_hdr_len(pkt),
net_pkt_ipv6_ext_len(pkt),
offset,
net_pkt_ip_hdr_len(pkt) +
net_pkt_ipv6_ext_len(pkt),
net_buf_frags_len(pkt->frags));
return NULL;
}
return (struct net_udp_hdr *)(frag->data + offset);
}
void net_pkt_init(void)
{
NET_DBG("Allocating %u RX (%zu bytes), %u TX (%zu bytes), "

View file

@ -57,6 +57,19 @@ struct net_icmp_hdr *net_icmp_header_fits(struct net_pkt *pkt,
return NULL;
}
struct net_udp_hdr *net_pkt_udp_data(struct net_pkt *pkt);
static inline
struct net_udp_hdr *net_udp_header_fits(struct net_pkt *pkt,
struct net_udp_hdr *hdr)
{
if (net_header_fits(pkt, (u8_t *)hdr, sizeof(*hdr))) {
return hdr;
}
return NULL;
}
#if defined(CONFIG_NET_IPV4)
extern u16_t net_calc_chksum_ipv4(struct net_pkt *pkt);
#endif /* CONFIG_NET_IPV4 */

279
subsys/net/ip/udp.c Normal file
View file

@ -0,0 +1,279 @@
/** @file
* @brief UDP packet helpers.
*/
/*
* Copyright (c) 2017 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#if defined(CONFIG_NET_DEBUG_UDP)
#define SYS_LOG_DOMAIN "net/udp"
#define NET_LOG_ENABLED 1
#endif
#include "net_private.h"
#include "udp_internal.h"
#define PKT_WAIT_TIME K_SECONDS(1)
struct net_pkt *net_udp_append_raw(struct net_pkt *pkt,
u16_t src_port,
u16_t dst_port)
{
struct net_buf *frag;
u16_t offset;
net_pkt_append(pkt, sizeof(src_port), (u8_t *)&src_port,
PKT_WAIT_TIME);
net_pkt_append(pkt, sizeof(dst_port), (u8_t *)&dst_port,
PKT_WAIT_TIME);
net_pkt_append_be16(pkt, net_pkt_get_len(pkt) -
net_pkt_ip_hdr_len(pkt) -
net_pkt_ipv6_ext_len(pkt));
frag = net_frag_get_pos(pkt, net_pkt_ip_hdr_len(pkt) +
net_pkt_ipv6_ext_len(pkt) +
sizeof(struct net_udp_hdr),
&offset);
if (frag) {
net_pkt_set_appdata(pkt, frag->data + offset);
}
return pkt;
}
struct net_pkt *net_udp_insert_raw(struct net_pkt *pkt,
u16_t offset,
u16_t src_port,
u16_t dst_port)
{
struct net_buf *frag, *prev, *udp;
u16_t pos;
frag = net_frag_get_pos(pkt, offset, &pos);
if (!frag && pos == 0xffff) {
NET_DBG("Offset %d out of pkt len %zd",
offset, net_pkt_get_len(pkt));
return NULL;
}
/* We can only insert the UDP header between existing two
* fragments.
*/
if (frag && pos != 0) {
NET_DBG("Cannot insert UDP data into offset %d", offset);
return NULL;
}
if (pkt->frags != frag) {
struct net_buf *tmp = pkt->frags;
prev = NULL;
while (tmp->frags) {
if (tmp->frags == frag) {
prev = tmp;
break;
}
tmp = tmp->frags;
}
} else {
prev = pkt->frags;
}
if (!prev) {
goto fail;
}
udp = net_pkt_get_frag(pkt, PKT_WAIT_TIME);
if (!udp) {
goto fail;
}
/* Source and destination ports are already in network byte order */
net_buf_add_mem(udp, &src_port, sizeof(src_port));
net_buf_add_mem(udp, &dst_port, sizeof(dst_port));
net_buf_add_be16(udp, net_pkt_get_len(pkt) -
net_pkt_ip_hdr_len(pkt) -
net_pkt_ipv6_ext_len(pkt) +
sizeof(struct net_udp_hdr));
net_buf_add_be16(udp, 0); /* chksum */
net_buf_frag_insert(prev, udp);
frag = net_frag_get_pos(pkt, net_pkt_ip_hdr_len(pkt) +
net_pkt_ipv6_ext_len(pkt) +
sizeof(struct net_udp_hdr),
&pos);
if (frag) {
net_pkt_set_appdata(pkt, frag->data + pos);
}
return pkt;
fail:
NET_DBG("Cannot insert UDP header into %p", pkt);
return NULL;
}
struct net_buf *net_udp_set_chksum(struct net_pkt *pkt, struct net_buf *frag)
{
struct net_udp_hdr *hdr;
u16_t chksum = 0;
u16_t pos;
hdr = net_pkt_udp_data(pkt);
if (net_udp_header_fits(pkt, hdr)) {
hdr->chksum = 0;
hdr->chksum = ~net_calc_chksum_udp(pkt);
return frag;
}
/* We need to set the checksum to 0 first before the calc */
frag = net_pkt_write(pkt, frag,
net_pkt_ip_hdr_len(pkt) +
net_pkt_ipv6_ext_len(pkt) +
2 + 2 + 2 /* src + dst + len */,
&pos, sizeof(chksum), (u8_t *)&chksum,
PKT_WAIT_TIME);
chksum = ~net_calc_chksum_udp(pkt);
frag = net_pkt_write(pkt, frag, pos - 2, &pos, sizeof(chksum),
(u8_t *)&chksum, PKT_WAIT_TIME);
NET_ASSERT(frag);
return frag;
}
u16_t net_udp_get_chksum(struct net_pkt *pkt, struct net_buf *frag)
{
struct net_udp_hdr *hdr;
u16_t chksum;
u16_t pos;
hdr = net_pkt_udp_data(pkt);
if (net_udp_header_fits(pkt, hdr)) {
return hdr->chksum;
}
frag = net_frag_read(frag,
net_pkt_ip_hdr_len(pkt) +
net_pkt_ipv6_ext_len(pkt) +
2 + 2 + 2 /* src + dst + len */,
&pos, sizeof(chksum), (u8_t *)&chksum);
NET_ASSERT(frag);
return chksum;
}
struct net_udp_hdr *net_udp_get_hdr(struct net_pkt *pkt,
struct net_udp_hdr *hdr)
{
struct net_udp_hdr *udp_hdr;
struct net_buf *frag;
u16_t pos;
udp_hdr = net_pkt_udp_data(pkt);
if (net_udp_header_fits(pkt, udp_hdr)) {
return udp_hdr;
}
frag = net_frag_read(pkt->frags, net_pkt_ip_hdr_len(pkt) +
net_pkt_ipv6_ext_len(pkt),
&pos, sizeof(hdr->src_port),
(u8_t *)&hdr->src_port);
frag = net_frag_read(frag, pos, &pos, sizeof(hdr->dst_port),
(u8_t *)&hdr->dst_port);
frag = net_frag_read(frag, pos, &pos, sizeof(hdr->len),
(u8_t *)&hdr->len);
frag = net_frag_read(frag, pos, &pos, sizeof(hdr->chksum),
(u8_t *)&hdr->chksum);
if (!frag) {
NET_ASSERT(frag);
return NULL;
}
return hdr;
}
struct net_udp_hdr *net_udp_set_hdr(struct net_pkt *pkt,
struct net_udp_hdr *hdr)
{
struct net_buf *frag;
u16_t pos;
if (net_udp_header_fits(pkt, hdr)) {
return hdr;
}
frag = net_pkt_write(pkt, pkt->frags, net_pkt_ip_hdr_len(pkt) +
net_pkt_ipv6_ext_len(pkt),
&pos, sizeof(hdr->src_port),
(u8_t *)&hdr->src_port, PKT_WAIT_TIME);
frag = net_pkt_write(pkt, frag, pos, &pos, sizeof(hdr->dst_port),
(u8_t *)&hdr->dst_port, PKT_WAIT_TIME);
frag = net_pkt_write(pkt, frag, pos, &pos, sizeof(hdr->len),
(u8_t *)&hdr->len, PKT_WAIT_TIME);
frag = net_pkt_write(pkt, frag, pos, &pos, sizeof(hdr->chksum),
(u8_t *)&hdr->chksum, PKT_WAIT_TIME);
if (!frag) {
NET_ASSERT(frag);
return NULL;
}
return hdr;
}
struct net_pkt *net_udp_append(struct net_context *context,
struct net_pkt *pkt,
u16_t port)
{
/* Append writes using *_be16() so it swap the port here */
return net_udp_append_raw(pkt,
net_sin((struct sockaddr *)
&context->local)->sin_port,
port);
}
struct net_pkt *net_udp_insert(struct net_context *context,
struct net_pkt *pkt,
u16_t offset,
u16_t port)
{
return net_udp_insert_raw(pkt,
offset,
net_sin((struct sockaddr *)
&context->local)->sin_port,
port);
}
int net_udp_register(const struct sockaddr *remote_addr,
const struct sockaddr *local_addr,
u16_t remote_port,
u16_t local_port,
net_conn_cb_t cb,
void *user_data,
struct net_conn_handle **handle)
{
return net_conn_register(IPPROTO_UDP, remote_addr, local_addr,
remote_port, local_port, cb, user_data,
handle);
}
int net_udp_unregister(struct net_conn_handle *handle)
{
return net_conn_unregister(handle);
}
void net_udp_init(void)
{
}

View file

@ -40,13 +40,11 @@ static inline struct net_pkt *net_udp_append_raw(struct net_pkt *pkt,
u16_t src_port,
u16_t dst_port)
{
NET_UDP_HDR(pkt)->src_port = htons(src_port);
NET_UDP_HDR(pkt)->dst_port = htons(dst_port);
net_buf_add(pkt->frags, sizeof(struct net_udp_hdr));
NET_UDP_HDR(pkt)->len = htons(net_pkt_get_len(pkt) -
net_pkt_ip_hdr_len(pkt));
net_pkt_append_be16(pkt, src_port);
net_pkt_append_be16(pkt, dst_port);
net_pkt_append_be16(pkt, net_pkt_get_len(pkt) -
net_pkt_ip_hdr_len(pkt) -
net_pkt_ipv6_ext_len(pkt));
net_pkt_set_appdata(pkt, net_pkt_udp_data(pkt) +
sizeof(struct net_udp_hdr));
@ -54,6 +52,68 @@ static inline struct net_pkt *net_udp_append_raw(struct net_pkt *pkt,
return pkt;
}
#ifndef NET_UDP_PKT_WAIT_TIME
#define NET_UDP_PKT_WAIT_TIME K_SECONDS(1)
#endif
static inline struct net_buf *net_udp_set_chksum(struct net_pkt *pkt,
struct net_buf *frag)
{
u16_t chksum;
u16_t pos;
frag = net_pkt_write_be16(pkt, pkt->frags,
net_pkt_ip_hdr_len(pkt) +
net_pkt_ipv6_ext_len(pkt) +
2 + 2 + 2 /* src + dst + len */,
&pos, 0);
chksum = ~net_calc_chksum_udp(pkt);
frag = net_pkt_write(pkt, frag, pos - 2, &pos, sizeof(chksum),
(u8_t *)&chksum, NET_UDP_PKT_WAIT_TIME);
NET_ASSERT(frag);
return frag;
}
static inline u16_t net_udp_get_chksum(struct net_pkt *pkt,
struct net_buf *frag)
{
u16_t chksum;
u16_t pos;
frag = net_frag_read_be16(pkt->frags,
net_pkt_ip_hdr_len(pkt) +
net_pkt_ipv6_ext_len(pkt) +
2 + 2 + 2 /* src + dst + len */,
&pos, &chksum);
NET_ASSERT(frag);
return chksum;
}
static inline struct net_udp_hdr *net_udp_get_hdr(struct net_pkt *pkt,
struct net_udp_udp *hdr)
{
struct net_buf *frag = pkt->frags;
u16_t pos;
frag = net_frag_read_be16(frag, net_pkt_ip_hdr_len(pkt) +
net_pkt_ipv6_ext_len(pkt),
&pos, &hdr->src_port);
frag = net_frag_read_be16(frag, pos, &pos, &hdr->dst_port);
frag = net_frag_read_be16(frag, pos, &pos, &hdr->len);
frag = net_frag_read_be16(frag, pos, &pos, &hdr->chksum);
if (!frag) {
NET_ASSERT(frag);
return NULL;
}
return hdr;
}
/**
* @brief Append UDP packet into net_pkt
*

View file

@ -0,0 +1,161 @@
/** @file
@brief UDP data handler
This is not to be included by the application and is only used by
core IP stack.
*/
/*
* Copyright (c) 2017 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __UDP_INTERNAL_H
#define __UDP_INTERNAL_H
#include <zephyr/types.h>
#include <net/net_core.h>
#include <net/net_ip.h>
#include <net/net_pkt.h>
#include <net/net_context.h>
#include "connection.h"
#ifdef __cplusplus
extern "C" {
#endif
#if defined(CONFIG_NET_UDP)
/**
* @brief Append UDP packet into net_pkt
*
* @param pkt Network packet
* @param src_port Source port in host byte order.
* @param dst_port Destination port in host byte order.
*
* @return Return network packet that contains the UDP packet.
*/
struct net_pkt *net_udp_append_raw(struct net_pkt *pkt,
u16_t src_port,
u16_t dst_port);
/**
* @brief Insert UDP packet into net_pkt chain. The UDP header is added
* right after the IP header which is after first fragment.
*
* @param pkt Network packet
* @param offset Offset where to insert (typically after IP header)
* @param src_port Source port in host byte order.
* @param dst_port Destination port in host byte order.
*
* @return Return network packet that contains the UDP packet.
*/
struct net_pkt *net_udp_insert_raw(struct net_pkt *pkt,
u16_t offset,
u16_t src_port,
u16_t dst_port);
/**
* @brief Set UDP checksum in network packet.
*
* @param pkt Network packet
* @param frag Fragment where to start calculating the offset.
* Typically this is set to pkt->frags by the caller.
*
* @return Return the actual fragment where the checksum was written.
*/
struct net_buf *net_udp_set_chksum(struct net_pkt *pkt, struct net_buf *frag);
/**
* @brief Get UDP checksum from network packet.
*
* @param pkt Network packet
* @param frag Fragment where to start calculating the offset.
* Typically this is set to pkt->frags by the caller.
*
* @return Return the checksum in host byte order.
*/
u16_t net_udp_get_chksum(struct net_pkt *pkt, struct net_buf *frag);
/**
* @brief Append UDP packet into net_pkt
*
* @param context Network context for a connection
* @param pkt Network packet
* @param port Destination port in network byte order.
*
* @return Return network packet that contains the UDP packet.
*/
struct net_pkt *net_udp_append(struct net_context *context,
struct net_pkt *pkt,
u16_t port);
/**
* @brief Insert UDP packet into net_pkt after specific offset.
*
* @param context Network context for a connection
* @param pkt Network packet
* @param offset Offset where to insert (typically after IP header)
* @param port Destination port in network byte order.
*
* @return Return network packet that contains the UDP packet or NULL if
* there is an failure.
*/
struct net_pkt *net_udp_insert(struct net_context *context,
struct net_pkt *pkt,
u16_t offset,
u16_t port);
#else
#define net_udp_append_raw(pkt, src_port, dst_port) (pkt)
#define net_udp_append(context, pkt, port) (pkt)
#define net_udp_insert_raw(pkt, offset, src_port, dst_port) (pkt)
#define net_udp_insert(context, pkt, offset, port) (pkt)
#define net_udp_get_chksum(pkt, frag) (0)
#define net_udp_set_chksum(pkt, frag) NULL
#endif /* CONFIG_NET_UDP */
/**
* @brief Register a callback to be called when UDP packet
* is received corresponding to received packet.
*
* @param remote_addr Remote address of the connection end point.
* @param local_addr Local address of the connection end point.
* @param remote_port Remote port of the connection end point.
* @param local_port Local port of the connection end point.
* @param cb Callback to be called
* @param user_data User data supplied by caller.
* @param handle UDP handle that can be used when unregistering
*
* @return Return 0 if the registration succeed, <0 otherwise.
*/
int net_udp_register(const struct sockaddr *remote_addr,
const struct sockaddr *local_addr,
u16_t remote_port,
u16_t local_port,
net_conn_cb_t cb,
void *user_data,
struct net_conn_handle **handle);
/**
* @brief Unregister UDP handler.
*
* @param handle Handle from registering.
*
* @return Return 0 if the unregistration succeed, <0 otherwise.
*/
int net_udp_unregister(struct net_conn_handle *handle);
#if defined(CONFIG_NET_UDP)
void net_udp_init(void);
#else
#define net_udp_init(...)
#endif
#ifdef __cplusplus
}
#endif
#endif /* __UDP_INTERNAL_H */

View file

@ -21,6 +21,7 @@
#include <net/net_ip.h>
#include <net/net_if.h>
#include <net/net_context.h>
#include <net/udp.h>
#include "net_private.h"
@ -1074,6 +1075,8 @@ static void net_context_iface_init(struct net_if *iface)
static int tester_send(struct net_if *iface, struct net_pkt *pkt)
{
struct net_udp_hdr hdr, *udp_hdr;
if (!pkt->frags) {
TC_ERROR("No data to send!\n");
return -ENODATA;
@ -1110,9 +1113,16 @@ static int tester_send(struct net_if *iface, struct net_pkt *pkt)
net_ipaddr_copy(&NET_IPV4_HDR(pkt)->dst, &addr);
}
port = NET_UDP_HDR(pkt)->src_port;
NET_UDP_HDR(pkt)->src_port = NET_UDP_HDR(pkt)->dst_port;
NET_UDP_HDR(pkt)->dst_port = port;
udp_hdr = net_udp_get_hdr(pkt, &hdr);
if (!udp_hdr) {
TC_ERROR("UDP data receive failed.");
goto out;
}
port = udp_hdr->src_port;
udp_hdr->src_port = udp_hdr->dst_port;
udp_hdr->dst_port = port;
net_udp_set_hdr(pkt, udp_hdr);
if (net_recv_data(iface, pkt) < 0) {
TC_ERROR("Data receive failed.");

View file

@ -15,9 +15,15 @@ CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_NET_IF_UNICAST_IPV4_ADDR_COUNT=1
CONFIG_NET_DEBUG_IF=y
CONFIG_NET_DEBUG_CORE=y
CONFIG_NET_DEBUG_ICMPV4=y
CONFIG_NET_DEBUG_DHCPV4=y
CONFIG_NET_DEBUG_IPV4=y
CONFIG_NET_DEBUG_CONN=y
CONFIG_NET_IPV4=y
CONFIG_NET_IPV6=n
#CONFIG_SYS_LOG_NET_LEVEL=4
#CONFIG_NET_DEBUG_L2_ETHERNET=y
#CONFIG_NET_DEBUG_NET_PKT=y
CONFIG_SYS_LOG_NET_LEVEL=2
CONFIG_NET_MGMT=y
CONFIG_NET_MGMT_EVENT=y

View file

@ -22,6 +22,7 @@
#include <net/dhcpv4.h>
#include <net/ethernet.h>
#include <net/net_mgmt.h>
#include <net/udp.h>
#include <tc_util.h>
@ -250,7 +251,9 @@ static void set_udp_header(struct net_pkt *pkt)
struct net_udp_hdr *udp;
u16_t length;
udp = NET_UDP_HDR(pkt);
udp = (struct net_udp_hdr *)((u8_t *)(NET_IPV4_HDR(pkt)) +
sizeof(struct net_ipv4_hdr));
udp->src_port = htons(SERVER_PORT);
udp->dst_port = htons(CLIENT_PORT);
@ -474,7 +477,6 @@ static int tester_send(struct net_if *iface, struct net_pkt *pkt)
}
parse_dhcp_message(pkt, &msg);
net_pkt_unref(pkt);
if (msg.type == DISCOVER) {
/* Reply with DHCPv4 offer message */
@ -500,6 +502,7 @@ static int tester_send(struct net_if *iface, struct net_pkt *pkt)
return -EINVAL;
}
net_pkt_unref(pkt);
return NET_OK;
}

View file

@ -25,7 +25,7 @@
#include "net_private.h"
#include "ipv6.h"
#include "udp.h"
#include "udp_internal.h"
#if defined(CONFIG_NET_DEBUG_IPV6)
#define DBG(fmt, ...) printk(fmt, ##__VA_ARGS__)
@ -664,8 +664,7 @@ static void send_ipv6_fragment(void)
NET_IPV6_HDR(pkt)->len[1] = total_len -
NET_IPV6_HDR(pkt)->len[0] * 256;
NET_UDP_HDR(pkt)->chksum = 0;
NET_UDP_HDR(pkt)->chksum = ~net_calc_chksum_udp(pkt);
net_udp_set_chksum(pkt, pkt->frags);
test_failed = false;

View file

@ -1,6 +1,7 @@
CONFIG_NETWORKING=y
CONFIG_NET_L2_DUMMY=y
CONFIG_NET_UDP=y
CONFIG_NET_TCP=n
CONFIG_NET_MAX_CONN=64
CONFIG_NET_CONN_CACHE=y
CONFIG_NET_IPV6=y
@ -21,6 +22,7 @@ CONFIG_NET_DEBUG_CORE=y
CONFIG_NET_DEBUG_CONN=y
#CONFIG_NET_DEBUG_NET_PKT=y
#CONFIG_NET_DEBUG_IF=y
CONFIG_SYS_LOG_NET_LEVEL=2
# Turn off UDP checksum checking as the test fails otherwise.
CONFIG_NET_UDP_CHECKSUM=n

View file

@ -22,6 +22,7 @@
#include <net/net_pkt.h>
#include <net/net_ip.h>
#include <net/ethernet.h>
#include <net/udp.h>
#include <tc_util.h>
@ -31,11 +32,17 @@
#define DBG(fmt, ...)
#endif
#include "udp.h"
#include "udp_internal.h"
#if defined(CONFIG_NET_DEBUG_UDP)
#define NET_LOG_ENABLED 1
#endif
#include "net_private.h"
static bool test_failed;
static bool fail = true;
static struct k_sem recv_lock;
static char payload[] = { 'f', 'o', 'o', 'b', 'a', 'r', '\0' };
struct net_udp_context {
u8_t mac_addr[sizeof(struct net_eth_addr)];
@ -171,6 +178,8 @@ static enum net_verdict test_fail(struct net_conn *conn,
return NET_DROP;
}
#define NET_UDP_HDR(pkt) ((struct net_udp_hdr *)(net_pkt_udp_data(pkt)))
static void setup_ipv6_udp(struct net_pkt *pkt,
struct in6_addr *remote_addr,
struct in6_addr *local_addr,
@ -181,7 +190,7 @@ static void setup_ipv6_udp(struct net_pkt *pkt,
NET_IPV6_HDR(pkt)->tcflow = 0;
NET_IPV6_HDR(pkt)->flow = 0;
NET_IPV6_HDR(pkt)->len[0] = 0;
NET_IPV6_HDR(pkt)->len[1] = NET_UDPH_LEN;
NET_IPV6_HDR(pkt)->len[1] = NET_UDPH_LEN + strlen(payload);
NET_IPV6_HDR(pkt)->nexthdr = IPPROTO_UDP;
NET_IPV6_HDR(pkt)->hop_limit = 255;
@ -190,14 +199,114 @@ static void setup_ipv6_udp(struct net_pkt *pkt,
net_ipaddr_copy(&NET_IPV6_HDR(pkt)->dst, local_addr);
net_pkt_set_ip_hdr_len(pkt, sizeof(struct net_ipv6_hdr));
NET_UDP_HDR(pkt)->src_port = htons(remote_port);
NET_UDP_HDR(pkt)->dst_port = htons(local_port);
net_pkt_set_ipv6_ext_len(pkt, 0);
net_buf_add(pkt->frags, net_pkt_ip_hdr_len(pkt) +
sizeof(struct net_udp_hdr));
NET_UDP_HDR(pkt)->src_port = htons(remote_port);
NET_UDP_HDR(pkt)->dst_port = htons(local_port);
net_buf_add_mem(pkt->frags, payload, strlen(payload));
}
u8_t ipv6_hop_by_hop_ext_hdr[] = {
/* Next header UDP */
0x11,
/* Length (multiple of 8 octets) */
0x0C,
/* Experimental extension */
0x3e,
/* Length in bytes */
0x20,
0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
0x49, 0x4A, 0x4B, 0x4C, 0x4E, 0x4F, 0x50, 0x51,
0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
0x5A, 0x5B, 0x5C, 0x5D, 0x5F, 0x60, 0x61, 0x62,
/* Another experimental extension */
0x3e,
/* Length in bytes */
0x20,
0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A,
0x6B, 0x6C, 0x6D, 0x6F, 0x70, 0x71, 0x72, 0x73,
0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B,
0x7C, 0x7D, 0x7E, 0x21, 0x22, 0x23, 0x24, 0x25,
/* Another experimental extension */
0x3e,
/* Length in bytes */
0x20,
0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D,
0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D,
0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45,
};
static void setup_ipv6_udp_long(struct net_pkt *pkt,
struct in6_addr *remote_addr,
struct in6_addr *local_addr,
u16_t remote_port,
u16_t local_port)
{
struct net_udp_hdr hdr, *udp_hdr;
struct net_ipv6_hdr ipv6;
ipv6.vtc = 0x60;
ipv6.tcflow = 0;
ipv6.flow = 0;
ipv6.len[0] = 0;
ipv6.len[1] = NET_UDPH_LEN + strlen(payload) +
sizeof(ipv6_hop_by_hop_ext_hdr);
ipv6.nexthdr = 0; /* HBHO */
ipv6.hop_limit = 255;
net_ipaddr_copy(&ipv6.src, remote_addr);
net_ipaddr_copy(&ipv6.dst, local_addr);
net_pkt_set_ip_hdr_len(pkt, sizeof(struct net_ipv6_hdr));
hdr.src_port = htons(remote_port);
hdr.dst_port = htons(local_port);
net_pkt_append_all(pkt, sizeof(ipv6), (u8_t *)&ipv6, K_FOREVER);
net_pkt_append_all(pkt, sizeof(ipv6_hop_by_hop_ext_hdr),
ipv6_hop_by_hop_ext_hdr, K_FOREVER);
net_pkt_append_all(pkt, sizeof(hdr), (u8_t *)&hdr, K_FOREVER);
net_pkt_append_all(pkt, strlen(payload), payload, K_FOREVER);
net_pkt_set_ipv6_ext_len(pkt, sizeof(ipv6_hop_by_hop_ext_hdr));
udp_hdr = net_udp_get_hdr(pkt, &hdr);
if (udp_hdr != &hdr) {
TC_ERROR("Invalid UDP header pointer\n");
return;
}
udp_hdr->src_port = htons(remote_port);
udp_hdr->dst_port = htons(local_port);
net_udp_set_hdr(pkt, &hdr);
udp_hdr = net_udp_get_hdr(pkt, &hdr);
if (udp_hdr != &hdr) {
TC_ERROR("Invalid UDP header pointer %p\n", udp_hdr);
test_failed = true;
return;
}
if (udp_hdr->src_port != htons(remote_port)) {
TC_ERROR("Invalid remote port, should have been %d was %d\n",
remote_port, ntohs(udp_hdr->src_port));
test_failed = true;
}
if (udp_hdr->dst_port != htons(local_port)) {
TC_ERROR("Invalid local port, should have been %d was %d\n",
local_port, ntohs(udp_hdr->dst_port));
test_failed = true;
}
net_hexdump_frags("frag", pkt);
}
static void setup_ipv4_udp(struct net_pkt *pkt,
@ -210,7 +319,7 @@ static void setup_ipv4_udp(struct net_pkt *pkt,
NET_IPV4_HDR(pkt)->tos = 0;
NET_IPV4_HDR(pkt)->len[0] = 0;
NET_IPV4_HDR(pkt)->len[1] = NET_UDPH_LEN +
sizeof(struct net_ipv4_hdr);
sizeof(struct net_ipv4_hdr) + strlen(payload);
NET_IPV4_HDR(pkt)->proto = IPPROTO_UDP;
@ -218,14 +327,15 @@ static void setup_ipv4_udp(struct net_pkt *pkt,
net_ipaddr_copy(&NET_IPV4_HDR(pkt)->dst, local_addr);
net_pkt_set_ip_hdr_len(pkt, sizeof(struct net_ipv4_hdr));
NET_UDP_HDR(pkt)->src_port = htons(remote_port);
NET_UDP_HDR(pkt)->dst_port = htons(local_port);
net_pkt_set_ipv6_ext_len(pkt, 0);
net_buf_add(pkt->frags, net_pkt_ip_hdr_len(pkt) +
sizeof(struct net_udp_hdr));
NET_UDP_HDR(pkt)->src_port = htons(remote_port);
NET_UDP_HDR(pkt)->dst_port = htons(local_port);
net_buf_add_mem(pkt->frags, payload, strlen(payload));
}
#define TIMEOUT 200
@ -258,11 +368,59 @@ static bool send_ipv6_udp_msg(struct net_if *iface,
}
if (k_sem_take(&recv_lock, TIMEOUT)) {
printk("Timeout, packet not received\n");
if (expect_failure) {
return false;
} else {
return true;
} else {
printk("Timeout, packet not received\n");
return false;
}
}
/* Check that the returned user data is the same as what was given
* as a parameter.
*/
if (ud != returned_ud && !expect_failure) {
printk("IPv6 wrong user data %p returned, expected %p\n",
returned_ud, ud);
return false;
}
return !fail;
}
static bool send_ipv6_udp_long_msg(struct net_if *iface,
struct in6_addr *src,
struct in6_addr *dst,
u16_t src_port,
u16_t dst_port,
struct ud *ud,
bool expect_failure)
{
struct net_pkt *pkt;
struct net_buf *frag;
int ret;
pkt = net_pkt_get_reserve_tx(0, K_FOREVER);
frag = net_pkt_get_frag(pkt, K_FOREVER);
net_pkt_frag_add(pkt, frag);
net_pkt_set_iface(pkt, iface);
net_pkt_set_ll_reserve(pkt, net_buf_headroom(frag));
setup_ipv6_udp_long(pkt, src, dst, src_port, dst_port);
ret = net_recv_data(iface, pkt);
if (ret < 0) {
printk("Cannot recv pkt %p, ret %d\n", pkt, ret);
return false;
}
if (k_sem_take(&recv_lock, TIMEOUT)) {
if (expect_failure) {
return true;
} else {
printk("Timeout, packet not received\n");
return false;
}
}
@ -306,11 +464,11 @@ static bool send_ipv4_udp_msg(struct net_if *iface,
}
if (k_sem_take(&recv_lock, TIMEOUT)) {
printk("Timeout, packet not received\n");
if (expect_failure) {
return false;
} else {
return true;
} else {
printk("Timeout, packet not received\n");
return false;
}
}
@ -422,7 +580,8 @@ static bool run_tests(void)
user_data.local_addr = (struct sockaddr *)laddr; \
user_data.remote_port = rport; \
user_data.local_port = lport; \
user_data.test = #raddr"-"#laddr"-"#rport"-"#lport; \
user_data.test = "DST="#raddr"-SRC="#laddr"-RP="#rport \
"-LP="#lport; \
\
set_port(family, (struct sockaddr *)raddr, \
(struct sockaddr *)laddr, rport, lport); \
@ -448,7 +607,7 @@ static bool run_tests(void)
test_fail, INT_TO_POINTER(0), NULL); \
if (!ret) { \
printk("UDP register invalid match %s failed\n", \
#raddr"-"#laddr"-"#rport"-"#lport); \
"DST="#raddr"-SRC="#laddr"-RP="#rport"-LP="#lport); \
return false; \
}
@ -469,6 +628,15 @@ static bool run_tests(void)
return false; \
}
#define TEST_IPV6_LONG_OK(ud, raddr, laddr, rport, lport) \
st = send_ipv6_udp_long_msg(iface, raddr, laddr, rport, lport, ud, \
false); \
if (!st) { \
printk("%d: UDP long test \"%s\" fail\n", __LINE__, \
ud->test); \
return false; \
}
#define TEST_IPV4_OK(ud, raddr, laddr, rport, lport) \
st = send_ipv4_udp_msg(iface, raddr, laddr, rport, lport, ud, \
false); \
@ -481,7 +649,7 @@ static bool run_tests(void)
#define TEST_IPV6_FAIL(ud, raddr, laddr, rport, lport) \
st = send_ipv6_udp_msg(iface, raddr, laddr, rport, lport, ud, \
true); \
if (st) { \
if (!st) { \
printk("%d: UDP neg test \"%s\" fail\n", __LINE__, \
ud->test); \
return false; \
@ -490,7 +658,7 @@ static bool run_tests(void)
#define TEST_IPV4_FAIL(ud, raddr, laddr, rport, lport) \
st = send_ipv4_udp_msg(iface, raddr, laddr, rport, lport, ud, \
true); \
if (st) { \
if (!st) { \
printk("%d: UDP neg test \"%s\" fail\n", __LINE__, \
ud->test); \
return false; \
@ -499,6 +667,8 @@ static bool run_tests(void)
ud = REGISTER(AF_INET6, &any_addr6, &any_addr6, 1234, 4242);
TEST_IPV6_OK(ud, &in6addr_peer, &in6addr_my, 1234, 4242);
TEST_IPV6_OK(ud, &in6addr_peer, &in6addr_my, 1234, 4242);
TEST_IPV6_LONG_OK(ud, &in6addr_peer, &in6addr_my, 1234, 4242);
TEST_IPV6_LONG_OK(ud, &in6addr_peer, &in6addr_my, 1234, 4242);
TEST_IPV6_FAIL(ud, &in6addr_peer, &in6addr_my, 1234, 61400);
TEST_IPV6_FAIL(ud, &in6addr_peer, &in6addr_my, 1234, 61400);
UNREGISTER(ud);
@ -520,6 +690,8 @@ static bool run_tests(void)
ud = REGISTER(AF_INET6, NULL, &any_addr6, 1234, 4242);
TEST_IPV6_OK(ud, &in6addr_peer, &in6addr_my, 1234, 4242);
TEST_IPV6_OK(ud, &in6addr_peer, &in6addr_my, 1234, 4242);
TEST_IPV6_LONG_OK(ud, &in6addr_peer, &in6addr_my, 1234, 4242);
TEST_IPV6_LONG_OK(ud, &in6addr_peer, &in6addr_my, 1234, 4242);
TEST_IPV6_FAIL(ud, &in6addr_peer, &in6addr_my, 1234, 61400);
TEST_IPV6_FAIL(ud, &in6addr_peer, &in6addr_my, 1234, 61400);
UNREGISTER(ud);
@ -548,6 +720,7 @@ static bool run_tests(void)
ud = REGISTER(AF_UNSPEC, NULL, NULL, 0, 0);
TEST_IPV4_OK(ud, &in4addr_peer, &in4addr_my, 12345, 42421);
TEST_IPV6_OK(ud, &in6addr_peer, &in6addr_my, 12345, 42421);
TEST_IPV6_LONG_OK(ud, &in6addr_peer, &in6addr_my, 12345, 42421);
/* Remote addr same as local addr, these two will never match */
REGISTER(AF_INET6, &my_addr6, NULL, 1234, 4242);
@ -585,7 +758,9 @@ void main(void)
{
k_thread_priority_set(k_current_get(), K_PRIO_COOP(7));
if (run_tests()) {
test_failed = false;
if (run_tests() || !test_failed) {
TC_END_REPORT(TC_PASS);
} else {
TC_END_REPORT(TC_FAIL);