From: Srinivas Aji Date: Mon, 28 May 2007 18:39:43 +0000 (+0530) Subject: Put in Ethernet and LLC headers ourselves while sending BPDUs X-Git-Url: http://git.ipfire.org/?p=people%2Fms%2Frstp.git;a=commitdiff_plain;h=3cf368c157572231ec16ff1eb949ca2abfdeb326 Put in Ethernet and LLC headers ourselves while sending BPDUs Take BPDU contents from RSTPLIB but create the Ethernet and LLC headers ourselves. The packet send interface has been modified to take an iovec array so we can pass the headers and data to it without making copies into another flat buffer. RSTPLIB then doesn't even need to know the port MAC addresses if we add an interface to configure the bridge address. Signed-off-by: Srinivas Aji --- diff --git a/bridge_track.c b/bridge_track.c index 9a1ed6e..cd84cd9 100644 --- a/bridge_track.c +++ b/bridge_track.c @@ -52,7 +52,7 @@ struct ifdata { struct ifdata *next; int up; char name[IFNAMSIZ]; - unsigned char macaddr[6]; + unsigned char macaddr[ETH_ALEN]; int is_bridge; /* If bridge */ @@ -828,8 +828,20 @@ STP_OUT_tx_bpdu(IN int port_index, IN int vlan_id, TST(port != NULL, 0); TST(vlan_id == 0, 0); - packet_send(port->if_index, bpdu, - bpdu_len + sizeof(MAC_HEADER_T) + sizeof(ETH_HEADER_T)); + struct llc_header h; + memcpy(h.dest_addr, bridge_group_address, ETH_ALEN); + memcpy(h.src_addr, port->macaddr, ETH_ALEN); + /* bpdu_len excludes MAC and LLC headers */ + h.len8023 = htons(bpdu_len + 3); + h.d_sap = h.s_sap = STP_SAP; + h.llc_ui = 0x03; /* LLC UI packet */ + + struct iovec iov[2] = { + { .iov_base = &h, .iov_len = sizeof(h) }, + { .iov_base = bpdu + sizeof(h), .iov_len = bpdu_len } + }; + + packet_send(port->if_index, iov, 2, sizeof(h) + bpdu_len); return 0; } diff --git a/packet.c b/packet.c index 001f6d4..c3428b6 100644 --- a/packet.c +++ b/packet.c @@ -66,7 +66,7 @@ static void dump_packet(const unsigned char *buf, int cc) * To send/receive Spanning Tree packets we use PF_PACKET because * it allows the filtering we want but gives raw data */ -void packet_send(int ifindex, const unsigned char *data, int len) +void packet_send(int ifindex, const struct iovec *iov, int iov_count, int len) { int l; struct sockaddr_ll sl = { @@ -76,19 +76,33 @@ void packet_send(int ifindex, const unsigned char *data, int len) .sll_halen = ETH_ALEN, }; - memcpy(&sl.sll_addr, data, ETH_ALEN); + if (iov_count > 0 && iov[0].iov_len > ETH_ALEN) + memcpy(&sl.sll_addr, iov[0].iov_base, ETH_ALEN); + + struct msghdr msg = { + .msg_name = &sl, + .msg_namelen = sizeof(sl), + .msg_iov = (struct iovec *)iov, + .msg_iovlen = iov_count, + .msg_control = NULL, + .msg_controllen = 0, + .msg_flags = 0, + }; #ifdef PACKET_DEBUG printf("Transmit Dst index %d %02x:%02x:%02x:%02x:%02x:%02x\n", sl.sll_ifindex, sl.sll_addr[0], sl.sll_addr[1], sl.sll_addr[2], sl.sll_addr[3], sl.sll_addr[4], sl.sll_addr[5]); - - dump_packet(data, len); + + { + int i; + for (i = 0; i < iov_count; i++) + dump_packet(iov[i].iov_base, iov[i].iov_len); + } #endif - l = sendto(packet_event.fd, data, len, 0, - (struct sockaddr *) &sl, sizeof(sl)); + l = sendmsg(packet_event.fd, &msg, 0); if (l < 0) { if (errno != EWOULDBLOCK) diff --git a/packet.h b/packet.h index 0ae17b9..2ddaaf1 100644 --- a/packet.h +++ b/packet.h @@ -27,7 +27,9 @@ #include "epoll_loop.h" -void packet_send(int ifindex, const unsigned char *data, int len); +#include + +void packet_send(int ifindex, const struct iovec *iov, int iov_count, int len); int packet_sock_init(void);