@@ -794,6 +794,11 @@ int promisc(const char *dev)
794
794
return err;
795
795
}
796
796
797
+ #define ETH_JUMBO_FRAME_SIZE (9000 )
798
+ #define IEEE_8021Q_ETHER_TYPE (0x8100 )
799
+ #define MAC_ADDRESS_SIZE (6 )
800
+ #define VLAN_TAG_SIZE (4 )
801
+
797
802
void veth2tap_fun (std::shared_ptr<hostif_info_t > info)
798
803
{
799
804
SWSS_LOG_ENTER ();
@@ -804,7 +809,26 @@ void veth2tap_fun(std::shared_ptr<hostif_info_t> info)
804
809
{
805
810
// TODO convert to non blocking using select
806
811
807
- ssize_t size = read (info->packet_socket , buffer, sizeof (buffer));
812
+ struct msghdr msg;
813
+ memset (&msg, 0 , sizeof (struct msghdr ));
814
+
815
+ struct sockaddr_storage src_addr;
816
+
817
+ struct iovec iov[1 ];
818
+
819
+ iov[0 ].iov_base = buffer; // buffer for message
820
+ iov[0 ].iov_len = sizeof (buffer);
821
+
822
+ char control[0x1000 ]; // buffer for control messages
823
+
824
+ msg.msg_name = &src_addr;
825
+ msg.msg_namelen = sizeof (src_addr);
826
+ msg.msg_iov = iov;
827
+ msg.msg_iovlen = 1 ;
828
+ msg.msg_control = control;
829
+ msg.msg_controllen = sizeof (control);
830
+
831
+ ssize_t size = recvmsg (info->packet_socket , &msg, 0 );
808
832
809
833
if (size < 0 )
810
834
{
@@ -814,6 +838,47 @@ void veth2tap_fun(std::shared_ptr<hostif_info_t> info)
814
838
continue ;
815
839
}
816
840
841
+ if (size < (ssize_t )sizeof (ethhdr) || size > ETH_JUMBO_FRAME_SIZE)
842
+ {
843
+ SWSS_LOG_ERROR (" invalid ethernet frame length: %zu" , msg.msg_controllen );
844
+ continue ;
845
+ }
846
+
847
+ struct cmsghdr *cmsg;
848
+
849
+ for (cmsg = CMSG_FIRSTHDR (&msg); cmsg != NULL ; cmsg = CMSG_NXTHDR (&msg, cmsg))
850
+ {
851
+ if (cmsg->cmsg_level != SOL_PACKET || cmsg->cmsg_type != PACKET_AUXDATA)
852
+ continue ;
853
+
854
+ struct tpacket_auxdata * aux = (struct tpacket_auxdata *)CMSG_DATA (cmsg);
855
+
856
+ if ((aux->tp_status & TP_STATUS_VLAN_VALID) &&
857
+ (aux->tp_status & TP_STATUS_VLAN_TPID_VALID))
858
+ {
859
+ SWSS_LOG_DEBUG (" got vlan tci: 0x%x, vlanid: %d" , aux->tp_vlan_tci , aux->tp_vlan_tci & 0xFFF );
860
+
861
+ // inject vlan tag into frame
862
+
863
+ // for overlapping buffers
864
+ memmove (buffer + 2 * MAC_ADDRESS_SIZE + VLAN_TAG_SIZE,
865
+ buffer + 2 * MAC_ADDRESS_SIZE,
866
+ size - (2 * MAC_ADDRESS_SIZE));
867
+
868
+ uint16_t tci = htons (aux->tp_vlan_tci );
869
+ uint16_t tpid = htons (IEEE_8021Q_ETHER_TYPE);
870
+
871
+ uint16_t * pvlan = (uint16_t *)(buffer + 2 * MAC_ADDRESS_SIZE);
872
+
873
+ pvlan[0 ] = tpid;
874
+ pvlan[1 ] = tci;
875
+
876
+ size += VLAN_TAG_SIZE;
877
+
878
+ break ;
879
+ }
880
+ }
881
+
817
882
process_packet_for_fdb_event (buffer, size, info);
818
883
819
884
if (write (info->tapfd , buffer, size) < 0 )
@@ -934,6 +999,13 @@ bool hostif_create_tap_veth_forwarding(
934
999
return false ;
935
1000
}
936
1001
1002
+ int val = 1 ;
1003
+ if (setsockopt (packet_socket, SOL_PACKET, PACKET_AUXDATA, &val, sizeof (val)) < 0 )
1004
+ {
1005
+ SWSS_LOG_ERROR (" setsockopt() set PACKET_AUXDATA failed: %s" , strerror (errno));
1006
+ return false ;
1007
+ }
1008
+
937
1009
// bind to device
938
1010
939
1011
struct sockaddr_ll sock_address;
0 commit comments