On 3/6/18 3:02 PM, Lawrence Kreeger wrote: > Hello, > > I'm trying to run mstpd on a per VLAN basis using one traditional > linux bridge per VLAN. I'm running it on kernel version 4.12.4. It > works fine for untagged frames, but I'm having a problem with VLAN > tagged BPDUs arriving on the socket with the ifindex of the bridge > itself, and not the VLAN tagged interface. For example, I have a > tagged interface eth0.100 connected to the bridge "vlan100". When > packets arrive, they have the ifindex of vlan100, which mstpd doesn't > recognize as a valid spanning tree interface, so it drops them. Is > there something needed to be set in the kernel to get the ifindex of > eth0.100 instead? This is how mstpd opens the raw socket: > > > /* Berkeley Packet filter code to filter out spanning tree packets. > from tcpdump -s 1152 -dd stp > */ > static struct sock_filter stp_filter[] = { > { 0x28, 0, 0, 0x0000000c }, > { 0x25, 3, 0, 0x000005dc }, > { 0x30, 0, 0, 0x0000000e }, > { 0x15, 0, 1, 0x00000042 }, > { 0x6, 0, 0, 0x00000480 }, > { 0x6, 0, 0, 0x00000000 }, > }; > > /* > * Open up a raw packet socket to catch all 802.2 packets. > * and install a packet filter to only see STP (SAP 42) > * > * Since any bridged devices are already in promiscious mode > * no need to add multicast address. > */ > int packet_sock_init(void) > { > int s; > struct sock_fprog prog = > { > .len = sizeof(stp_filter) / sizeof(stp_filter[0]), > .filter = stp_filter, > }; > > s = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_802_2));
try ETH_P_ALL > if(s < 0) > { > ERROR("socket failed: %m"); > return -1; > } > > if(setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, &prog, sizeof(prog)) < 0) > ERROR("setsockopt packet filter failed: %m"); > else if(fcntl(s, F_SETFL, O_NONBLOCK) < 0) > ERROR("fcntl set nonblock failed: %m"); > else > { > packet_event.fd = s; > packet_event.handler = packet_rcv; And then packet_rcv using recvfrom: struct sockaddr_ll sll; char buf[4096]; socklen_t alen; int len; alen = sizeof(sll); len = recvfrom(sd, buf, sizeof(buf), 0, (struct sockaddr *)&sll, &alen); And sll.sll_ifindex will show vlan device indices. > > if(0 == add_epoll(&packet_event)) > return 0; > } > > close(s); > return -1; > } > > Thanks, Larry >