]> git.ipfire.org Git - people/ms/rstp.git/commitdiff
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 9a1ed6e97e45badb3927766ebe49485049de3f13..cd84cd9f79e18a4e7fb8e1d292fdab605e3a1b7f 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 001f6d4cfaed3f4ab70ef19f55cbce40a14dc9f1..c3428b6e7ebbc48558faba3c4321c0737742d91b 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 0ae17b9993a1b58c5e079c83dc7e147cacea6397..2ddaaf102c9a51e820222ae6daeacfc9a817cebd 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);