@@ -51,6 +51,7 @@ LOG_MODULE_REGISTER(net_test, NET_LOG_LEVEL);
5151#define VLAN_TAG_3 300
5252#define VLAN_TAG_4 400
5353#define VLAN_TAG_5 500
54+ #define VLAN_TAG_6 600
5455
5556#define NET_ETH_MAX_COUNT 2
5657
@@ -78,6 +79,7 @@ static struct in6_addr ll_addr = { { { 0xfe, 0x80, 0x43, 0xb8, 0, 0, 0, 0,
7879static struct net_if * eth_interfaces [NET_ETH_MAX_COUNT ];
7980static struct net_if * vlan_interfaces [NET_VLAN_MAX_COUNT ];
8081static struct net_if * dummy_interfaces [2 ];
82+ static struct net_if * embed_ll_interface ;
8183
8284static bool test_failed ;
8385static bool test_started ;
@@ -125,6 +127,13 @@ static int eth_tx(const struct device *dev, struct net_pkt *pkt)
125127 struct eth_context * context = dev -> data ;
126128 int ret ;
127129
130+ if (!IS_ENABLED (CONFIG_NET_L2_ETHERNET_RESERVE_HEADER )) {
131+ /* There should be at least two net_buf. The first one should contain
132+ * the link layer header.
133+ */
134+ zassert_not_equal (pkt -> buffer -> frags , NULL , "Only one net_buf in chain!" );
135+ }
136+
128137 zassert_equal_ptr (& eth_vlan_context , context ,
129138 "Context pointers do not match (%p vs %p)" ,
130139 eth_vlan_context , context );
@@ -159,15 +168,15 @@ static int eth_tx(const struct device *dev, struct net_pkt *pkt)
159168 return ret ;
160169}
161170
162- static enum ethernet_hw_caps eth_capabilities (const struct device * dev )
171+ static enum ethernet_hw_caps eth_vlan_capabilities (const struct device * dev )
163172{
164173 return ETHERNET_HW_VLAN ;
165174}
166175
167176static struct ethernet_api api_funcs = {
168177 .iface_api .init = eth_vlan_iface_init ,
169178
170- .get_capabilities = eth_capabilities ,
179+ .get_capabilities = eth_vlan_capabilities ,
171180 .send = eth_tx ,
172181};
173182
@@ -209,6 +218,37 @@ ETH_NET_DEVICE_INIT(eth_test, "eth_test", eth_init, NULL,
209218 & eth_vlan_context , NULL , CONFIG_ETH_INIT_PRIORITY ,
210219 & api_funcs , NET_ETH_MTU );
211220
221+ static int eth_tx_embed_ll_hdr (const struct device * dev , struct net_pkt * pkt )
222+ {
223+ if (IS_ENABLED (CONFIG_NET_L2_ETHERNET_RESERVE_HEADER )) {
224+ /* There should be only one net_buf */
225+ zassert_equal (pkt -> buffer -> frags , NULL , "More than one net_buf in chain!" );
226+ }
227+
228+ if (test_started ) {
229+ k_sleep (K_MSEC (10 ));
230+ k_sem_give (& wait_data );
231+ }
232+
233+ return 0 ;
234+ }
235+
236+ static enum ethernet_hw_caps eth_vlan_embed_ll_hdr_capabilities (const struct device * dev )
237+ {
238+ return ETHERNET_HW_VLAN ;
239+ }
240+
241+ static struct ethernet_api api_vlan_embed_ll_hdr_funcs = {
242+ .iface_api .init = eth_vlan_iface_init ,
243+
244+ .get_capabilities = eth_vlan_embed_ll_hdr_capabilities ,
245+ .send = eth_tx_embed_ll_hdr ,
246+ };
247+
248+ ETH_NET_DEVICE_INIT (eth_embed_ll_hdr_test , "eth_embed_ll_hdr_test" , eth_init , NULL ,
249+ & eth_vlan_context , NULL , CONFIG_ETH_INIT_PRIORITY ,
250+ & api_vlan_embed_ll_hdr_funcs , NET_ETH_MTU );
251+
212252struct net_if_test {
213253 uint8_t idx ; /* not used for anything, just a dummy value */
214254 uint8_t mac_addr [sizeof (struct net_eth_addr )];
@@ -317,6 +357,16 @@ static void iface_cb(struct net_if *iface, void *user_data)
317357 net_if_get_by_iface (iface ));
318358
319359 if (net_if_l2 (iface ) == & NET_L2_GET_NAME (ETHERNET )) {
360+ /* Ignore one special interface that is used to validate
361+ * ll header embedding.
362+ */
363+ if (strncmp (net_if_get_device (iface )-> name ,
364+ "eth_embed_ll_hdr_test" ,
365+ sizeof ("eth_embed_ll_hdr_test" ) - 1 ) == 0 ) {
366+ embed_ll_interface = iface ;
367+ return ;
368+ }
369+
320370 eth_interfaces [ud -> eth_if_count ++ ] = iface ;
321371 }
322372
@@ -836,6 +886,76 @@ ZTEST(net_vlan, test_vlan_ipv6_sendto_recvfrom)
836886 zassert_equal (ret , 0 , "close failed" );
837887}
838888
889+ /* This should be the last test to be run so add "zz" to the name */
890+ ZTEST (net_vlan , test_zz_vlan_embed_ll_hdr )
891+ {
892+ struct net_if * iface ;
893+ int ret ;
894+ int client_sock ;
895+ struct sockaddr_in6 client_addr ;
896+ struct sockaddr_in6 dest_addr ;
897+ struct net_if_addr * ifaddr ;
898+ ssize_t sent = 0 ;
899+ struct ifreq ifreq = { 0 };
900+ char ifname [CONFIG_NET_INTERFACE_NAME_LEN ];
901+
902+ /* embed ll interface addresses */
903+ static struct in6_addr my_vlan_addr = { { { 0x20 , 0x01 , 0x0d , 0xb8 , 0x90 , 0 , 0 , 0 ,
904+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0x2 } } };
905+
906+ static struct in6_addr peer_vlan_addr = { { { 0x20 , 0x01 , 0x0d , 0xb8 , 0x90 , 0 , 0 , 0 ,
907+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0x1 } } };
908+
909+ ret = net_eth_vlan_enable (embed_ll_interface , VLAN_TAG_6 );
910+ zassert_equal (ret , 0 , "Could not enable %d (%d)" , VLAN_TAG_6 , ret );
911+
912+ iface = net_eth_get_vlan_iface (embed_ll_interface , VLAN_TAG_6 );
913+ ret = net_eth_is_vlan_enabled (NULL , embed_ll_interface );
914+ zassert_equal (ret , true, "VLAN not enabled for interface" );
915+
916+ ifaddr = net_if_ipv6_addr_add (iface ,
917+ & my_vlan_addr ,
918+ NET_ADDR_MANUAL , 0 );
919+ if (!ifaddr ) {
920+ DBG ("Cannot add IPv6 address %s\n" ,
921+ net_sprint_ipv6_addr (& my_vlan_addr ));
922+ zassert_not_null (ifaddr , "vlan addr" );
923+ }
924+
925+ net_if_up (embed_ll_interface );
926+ net_if_up (iface );
927+
928+ test_started = true;
929+
930+ prepare_sock_udp_v6 ("2001:db8:90::2" , ANY_PORT , & client_sock , & client_addr );
931+
932+ ret = net_if_get_name (iface , ifname , sizeof (ifname ));
933+ zassert_true (ret > 0 , "cannot get interface name (%d/%s)" , ret , strerror (- ret ));
934+
935+ strncpy (ifreq .ifr_name , ifname , sizeof (ifreq .ifr_name ));
936+ ret = zsock_setsockopt (client_sock , SOL_SOCKET , SO_BINDTODEVICE , & ifreq ,
937+ sizeof (ifreq ));
938+ zassert_equal (ret , 0 , "SO_BINDTODEVICE failed, %d" , - errno );
939+
940+ ret = add_neighbor (iface , & peer_vlan_addr );
941+ zassert_true (ret , "Cannot add neighbor" );
942+
943+ net_ipaddr_copy (& dest_addr .sin6_addr , & peer_vlan_addr );
944+
945+ sent = zsock_sendto (client_sock , TEST_STR_SMALL , strlen (TEST_STR_SMALL ),
946+ 0 , (struct sockaddr * )& dest_addr , sizeof (dest_addr ));
947+ zassert_equal (sent , strlen (TEST_STR_SMALL ), "send (%d) failed %d/%s" ,
948+ sent , - errno , strerror (errno ));
949+
950+ if (k_sem_take (& wait_data , WAIT_TIME )) {
951+ DBG ("Timeout while waiting interface data\n" );
952+ zassert_false (true, "Timeout" );
953+ }
954+
955+ ret = zsock_close (client_sock );
956+ zassert_equal (ret , 0 , "close failed" );
957+ }
958+
839959static void * setup (void )
840960{
841961 test_vlan_setup ();
0 commit comments