@@ -518,27 +518,79 @@ static bool ethernet_fill_in_dst_on_ipv6_mcast(struct net_pkt *pkt,
518518#define ethernet_fill_in_dst_on_ipv6_mcast (...) false
519519#endif /* CONFIG_NET_IPV6 */
520520
521+ static inline size_t get_reserve_ll_header_size (struct net_if * iface )
522+ {
523+ bool is_vlan = false;
524+
525+ #if defined(CONFIG_NET_VLAN )
526+ if (net_if_l2 (iface ) == & NET_L2_GET_NAME (VIRTUAL )) {
527+ iface = net_eth_get_vlan_main (iface );
528+ is_vlan = true;
529+ }
530+ #endif
531+
532+ if (net_if_l2 (iface ) != & NET_L2_GET_NAME (ETHERNET )) {
533+ return 0U ;
534+ }
535+
536+ if (!IS_ENABLED (CONFIG_NET_L2_ETHERNET_RESERVE_HEADER )) {
537+ return 0U ;
538+ }
539+
540+ if (is_vlan ) {
541+ return sizeof (struct net_eth_vlan_hdr );
542+ } else {
543+ return sizeof (struct net_eth_hdr );
544+ }
545+ }
546+
521547static struct net_buf * ethernet_fill_header (struct ethernet_context * ctx ,
522548 struct net_if * iface ,
523549 struct net_pkt * pkt ,
524550 uint32_t ptype )
525551{
552+ struct net_if * orig_iface = iface ;
526553 struct net_buf * hdr_frag ;
527554 struct net_eth_hdr * hdr ;
528- size_t hdr_len = IS_ENABLED (CONFIG_NET_VLAN ) ?
529- sizeof (struct net_eth_vlan_hdr ) :
530- sizeof (struct net_eth_hdr );
555+ size_t reserve_ll_header ;
556+ size_t hdr_len ;
557+ bool is_vlan ;
558+
559+ is_vlan = IS_ENABLED (CONFIG_NET_VLAN ) &&
560+ net_eth_is_vlan_enabled (ctx , iface ) &&
561+ net_pkt_vlan_tag (pkt ) != NET_VLAN_TAG_UNSPEC ;
562+ if (is_vlan ) {
563+ orig_iface = net_eth_get_vlan_iface (iface , net_pkt_vlan_tag (pkt ));
564+ }
531565
532- hdr_frag = net_pkt_get_frag (pkt , hdr_len , NET_BUF_TIMEOUT );
533- if (!hdr_frag ) {
534- return NULL ;
566+ reserve_ll_header = get_reserve_ll_header_size (orig_iface );
567+ if (reserve_ll_header > 0 ) {
568+ hdr_len = reserve_ll_header ;
569+ hdr_frag = pkt -> buffer ;
570+
571+ NET_DBG ("Making room for link header %zd bytes" , hdr_len );
572+
573+ /* Make room for the header */
574+ net_buf_push (pkt -> buffer , hdr_len );
575+ } else {
576+ hdr_len = IS_ENABLED (CONFIG_NET_VLAN ) ?
577+ sizeof (struct net_eth_vlan_hdr ) :
578+ sizeof (struct net_eth_hdr );
579+
580+ hdr_frag = net_pkt_get_frag (pkt , hdr_len , NET_BUF_TIMEOUT );
581+ if (!hdr_frag ) {
582+ return NULL ;
583+ }
535584 }
536585
537- if (IS_ENABLED (CONFIG_NET_VLAN ) &&
538- net_eth_is_vlan_enabled (ctx , iface ) &&
539- net_pkt_vlan_tag (pkt ) != NET_VLAN_TAG_UNSPEC ) {
586+ if (is_vlan ) {
540587 struct net_eth_vlan_hdr * hdr_vlan ;
541588
589+ if (reserve_ll_header == 0U ) {
590+ hdr_len = sizeof (struct net_eth_vlan_hdr );
591+ net_buf_add (hdr_frag , hdr_len );
592+ }
593+
542594 hdr_vlan = (struct net_eth_vlan_hdr * )(hdr_frag -> data );
543595
544596 if (ptype == htons (NET_ETH_PTYPE_ARP ) ||
@@ -554,15 +606,19 @@ static struct net_buf *ethernet_fill_header(struct ethernet_context *ctx,
554606 hdr_vlan -> type = ptype ;
555607 hdr_vlan -> vlan .tpid = htons (NET_ETH_PTYPE_VLAN );
556608 hdr_vlan -> vlan .tci = htons (net_pkt_vlan_tci (pkt ));
557- net_buf_add (hdr_frag , sizeof (struct net_eth_vlan_hdr ));
558609
559610 print_vlan_ll_addrs (pkt , ntohs (hdr_vlan -> type ),
560611 net_pkt_vlan_tci (pkt ),
561- hdr_frag -> len ,
612+ hdr_len ,
562613 & hdr_vlan -> src , & hdr_vlan -> dst , false);
563614 } else {
564615 hdr = (struct net_eth_hdr * )(hdr_frag -> data );
565616
617+ if (reserve_ll_header == 0U ) {
618+ hdr_len = sizeof (struct net_eth_hdr );
619+ net_buf_add (hdr_frag , hdr_len );
620+ }
621+
566622 if (ptype == htons (NET_ETH_PTYPE_ARP ) ||
567623 (!ethernet_fill_in_dst_on_ipv4_mcast (pkt , & hdr -> dst ) &&
568624 !ethernet_fill_in_dst_on_ipv6_mcast (pkt , & hdr -> dst ))) {
@@ -574,13 +630,14 @@ static struct net_buf *ethernet_fill_header(struct ethernet_context *ctx,
574630 sizeof (struct net_eth_addr ));
575631
576632 hdr -> type = ptype ;
577- net_buf_add (hdr_frag , sizeof (struct net_eth_hdr ));
578633
579634 print_ll_addrs (pkt , ntohs (hdr -> type ),
580- hdr_frag -> len , & hdr -> src , & hdr -> dst );
635+ hdr_len , & hdr -> src , & hdr -> dst );
581636 }
582637
583- net_pkt_frag_insert (pkt , hdr_frag );
638+ if (reserve_ll_header == 0U ) {
639+ net_pkt_frag_insert (pkt , hdr_frag );
640+ }
584641
585642 return hdr_frag ;
586643}
@@ -605,14 +662,19 @@ static void ethernet_update_tx_stats(struct net_if *iface, struct net_pkt *pkt)
605662
606663static void ethernet_remove_l2_header (struct net_pkt * pkt )
607664{
665+ size_t reserve = get_reserve_ll_header_size (net_pkt_iface (pkt ));
608666 struct net_buf * buf ;
609667
610668 /* Remove the buffer added in ethernet_fill_header() */
611- buf = pkt -> buffer ;
612- pkt -> buffer = buf -> frags ;
613- buf -> frags = NULL ;
669+ if (reserve == 0U ) {
670+ buf = pkt -> buffer ;
671+ pkt -> buffer = buf -> frags ;
672+ buf -> frags = NULL ;
614673
615- net_pkt_frag_unref (buf );
674+ net_pkt_frag_unref (buf );
675+ } else {
676+ net_buf_pull (pkt -> buffer , reserve );
677+ }
616678}
617679
618680static int ethernet_send (struct net_if * iface , struct net_pkt * pkt )
@@ -813,8 +875,21 @@ enum net_l2_flags ethernet_flags(struct net_if *iface)
813875 return ctx -> ethernet_l2_flags ;
814876}
815877
878+ #if defined(CONFIG_NET_L2_ETHERNET_RESERVE_HEADER )
879+ static int ethernet_l2_alloc (struct net_if * iface , struct net_pkt * pkt ,
880+ size_t size , enum net_ip_protocol proto ,
881+ k_timeout_t timeout )
882+ {
883+ return net_pkt_alloc_buffer_with_reserve (pkt , size ,
884+ get_reserve_ll_header_size (iface ),
885+ proto , timeout );
886+ }
887+ #else
888+ #define ethernet_l2_alloc NULL
889+ #endif
890+
816891NET_L2_INIT (ETHERNET_L2 , ethernet_recv , ethernet_send , ethernet_enable ,
817- ethernet_flags );
892+ ethernet_flags , ethernet_l2_alloc );
818893
819894static void carrier_on_off (struct k_work * work )
820895{
0 commit comments