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:
parent
8476da9d9b
commit
3604c391e6
34 changed files with 1068 additions and 114 deletions
|
@ -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
70
include/net/udp.h
Normal 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 */
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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) */
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
/*
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
||||
/*
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
#include "rpl.h"
|
||||
|
||||
#include "connection.h"
|
||||
#include "udp.h"
|
||||
#include "udp_internal.h"
|
||||
#include "tcp.h"
|
||||
|
||||
#include "net_stats.h"
|
||||
|
|
|
@ -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), "
|
||||
|
|
|
@ -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
279
subsys/net/ip/udp.c
Normal 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)
|
||||
{
|
||||
}
|
|
@ -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
|
||||
*
|
||||
|
|
161
subsys/net/ip/udp_internal.h
Normal file
161
subsys/net/ip/udp_internal.h
Normal 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 */
|
|
@ -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.");
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue