Put in Ethernet and LLC headers ourselves while sending BPDUs
authorSrinivas Aji <Aji_Srinivas@emc.com>
Mon, 28 May 2007 18:39:43 +0000 (00:09 +0530)
committerSrinivas Aji <Aji_Srinivas@emc.com>
Wed, 27 Feb 2008 18:03:50 +0000 (23:33 +0530)
   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 <Aji_Srinivas@emc.com>
bridge_track.c
packet.c
packet.h

index 9a1ed6e..cd84cd9 100644 (file)
@@ -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;
 }
 
index 001f6d4..c3428b6 100644 (file)
--- 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)
index 0ae17b9..2ddaaf1 100644 (file)
--- 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 <sys/uio.h>
+
+void packet_send(int ifindex, const struct iovec *iov, int iov_count, int len);
 
 int packet_sock_init(void);