From 358260ffcc3985847f73f0882a09406f6d388dd9 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 25 Apr 2007 16:43:28 -0700 Subject: [PATCH] rstpd: working version This is the first version that works with modifications to bridge that are going into 2.6.22 Signed-off-by: Stephen Hemminger --- Makefile | 2 +- bridge-stp | 58 ++++++++++++++++++++++++++++++++-------- bridge_track.c | 69 ++++++++++++++++++++++++++++++++---------------- main.c | 8 ++++++ packet.c | 22 ++++++++------- rstplib/Makefile | 6 ++--- 6 files changed, 118 insertions(+), 47 deletions(-) diff --git a/Makefile b/Makefile index 7341fe2..4840a00 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ CTLSOURCES = ctl_main.c ctl_cli_wrap.c ctl_socket_client.c CTLOBJECTS = $(CTLSOURCES:.c=.o) CC=gcc -CFLAGS = -Wall -Werror -O2 -g -D_REENTRANT -D__LINUX__ -DVERSION=$(version) -DBUILD=$(build) -DSTP_DBG=1 -I. -I./include -I./rstplib +CFLAGS = -Wall -Werror -O2 -g -D_REENTRANT -D__LINUX__ -DVERSION=$(version) -DBUILD=$(build) -I. -I./include -I./rstplib all: rstpd rstpctl diff --git a/bridge-stp b/bridge-stp index c9ffcc6..49d5a41 100755 --- a/bridge-stp +++ b/bridge-stp @@ -1,27 +1,63 @@ #!/bin/bash # # Script to start/stop spanning tree called from kernel +# Make sure umask is sane +umask 022 -RSTPCTL=/sbin/rstpctl +# Set up a default search path. +PATH="/sbin:/usr/sbin:/bin:/usr/bin" +export PATH if [ $# -ne 2 ]; then echo "Usage: bridge-stp {start|stop}" exit 1 fi -BRIDGE=$1 +bridge=$1 +service=rstpd +pid_file=/var/run/${servicename}.pid + +# Set $pid to pids from /var/run* for {program}. $pid should be declared +# local in the caller. +# Returns LSB exit code for the 'status' action. +checkpid() { + pid= + if [ -f "$1" ] ; then + local line p + read line < "$pid_file" + for p in $line ; do + [ -z "${p//[0-9]/}" -a -d "/proc/$p" ] && pid="$pid $p" + done + if [ -n "$pid" ]; then + return 0 + fi + return 1 # "Program is dead and /var/run pid file exists" + fi + return 3 # "Program is not running" +} + +daemon() { + local pid + checkpid $pid_file + + [ -n "$pid" ] && return + # start it + /sbin/rstpd + RETVAL=$? + [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$service +} + +start() { + daemon +} case $2 in - start) exec $RSTPCTL rstp $BRIDGE on ;; - stop) exec $RSTPCTL rstp $BRIDGE off ;; + start) + daemon + exec /sbin/rstpctl $bridge on ;; + stop) + exec /sbin/rstpctl $bridge off ;; *) echo "Unknown action:" $2 echo "Usage: bridge-stp {start|stop}" exit 1 esac - - - - - - - diff --git a/bridge_track.c b/bridge_track.c index 18e59b7..67f6252 100644 --- a/bridge_track.c +++ b/bridge_track.c @@ -383,12 +383,38 @@ void delete_if(struct ifdata *ifc) free(ifc); } +static int stp_enabled(struct ifdata *br) +{ + char path[40 + IFNAMSIZ]; + sprintf(path, "/sys/class/net/%s/bridge/stp_state", br->name); + FILE *f = fopen(path, "r"); + if (!f) { + LOG("Open %s failed", path); + return 0; + } + int enabled = 0; + fscanf(f, "%d", &enabled); + fclose(f); + INFO("STP on %s state %d", br->name, enabled); + + return enabled == 2; /* ie user mode STP */ +} + void set_br_up(struct ifdata *br, int up) { - if (up != br->up) { + int stp_up = stp_enabled(br); + INFO("%s was %s stp was %s", br->name,up ? "up" : "down", br->stp_up ? "up" : "down"); + INFO("Set bridge %s %s stp %s" , br->name, + up ? "up" : "down", stp_up ? "up" : "down"); + + if (up != br->up) br->up = up; - if (br->do_stp) - up ? (void)init_bridge_stp(br) : clear_bridge_stp(br); + + if (br->stp_up != stp_up) { + if (stp_up) + init_bridge_stp(br); + else + clear_bridge_stp(br); } } @@ -545,23 +571,21 @@ int bridge_notify(int br_index, int if_index, int newlink, int up) void bridge_bpdu_rcv(int if_index, const unsigned char *data, int len) { struct ifdata *ifc = find_if(if_index); - BPDU_T bpdu; + BPDU_T *bpdu = (BPDU_T *) (data + sizeof(MAC_HEADER_T)); LOG("ifindex %d, len %d", if_index, len); if (!ifc) return; - TST(ifc->up && ifc->master->stp_up,); - - memset(&bpdu.eth, 0, sizeof(bpdu.eth)); - if (len > sizeof(bpdu) - sizeof(bpdu.eth)) - len = sizeof(bpdu) - sizeof(bpdu.eth); - memcpy(&bpdu.hdr, data, len); + TST(ifc->up,); + TST(ifc->master->stp_up,); + TST(len > sizeof(MAC_HEADER_T) + sizeof(ETH_HEADER_T) + sizeof(BPDU_HEADER_T),); /* Do some validation */ - TST(len >= 4,); - TST(bpdu.hdr.protocol[0] == 0 && bpdu.hdr.protocol[1] == 0,); - switch (bpdu.hdr.bpdu_type) { + if (bpdu->hdr.protocol[0] || bpdu->hdr.protocol[1]) + return; + + switch (bpdu->hdr.bpdu_type) { case BPDU_RSTP: TST(len >= 36,); case BPDU_CONFIG_TYPE: @@ -569,20 +593,20 @@ void bridge_bpdu_rcv(int if_index, const unsigned char *data, int len) /* 802.1w doesn't ask for this */ // TST(ntohs(*(uint16_t*)bpdu.body.message_age) // < ntohs(*(uint16_t*)bpdu.body.max_age), ); - TST(memcmp(bpdu.body.bridge_id, &ifc->master->bridge_id, 8) != 0 - || (ntohs(*(uint16_t *) bpdu.body.port_id) & 0xfff) != + TST(memcmp(bpdu->body.bridge_id, &ifc->master->bridge_id, 8) != 0 + || (ntohs(*(uint16_t *) bpdu->body.port_id) & 0xfff) != ifc->port_index,); break; case BPDU_TOPO_CHANGE_TYPE: break; default: - TST(0,); + LOG("Receive unknown bpdu type %x", bpdu->hdr.bpdu_type); + return; } // dump_hex(data, len); instance_begin(ifc->master); - int r = - STP_IN_rx_bpdu(0, ifc->port_index, &bpdu, len + sizeof(bpdu.eth)); + int r = STP_IN_rx_bpdu(0, ifc->port_index, bpdu, len); if (r) ERROR("STP_IN_rx_bpdu on port %s returned %s", ifc->name, STP_IN_get_error_explanation(r)); @@ -737,11 +761,10 @@ STP_OUT_tx_bpdu(IN int port_index, IN int vlan_id, struct ifdata *port = find_port(port_index); TST(port != NULL, 0); TST(vlan_id == 0, 0); - // dump_hex(bpdu + sizeof(MAC_HEADER_T) + sizeof(ETH_HEADER_T), - // bpdu_len - (sizeof(MAC_HEADER_T) + sizeof(ETH_HEADER_T))); - packet_send(port->if_index, - bpdu + sizeof(MAC_HEADER_T) + sizeof(ETH_HEADER_T), - bpdu_len); // The length we get excludes headers! + + packet_send(port->if_index, bpdu, + bpdu_len + sizeof(ETH_HEADER_T) + + sizeof(BPDU_HEADER_T) + sizeof(BPDU_BODY_T)); return 0; } diff --git a/main.c b/main.c index c89455b..2c78285 100644 --- a/main.c +++ b/main.c @@ -34,6 +34,7 @@ #include #include #include +#include static int become_daemon = 1; static int is_daemon = 0; @@ -71,9 +72,16 @@ int main(int argc, char *argv[]) TST(netsock_init() == 0, -1); TST(init_bridge_ops() == 0, -1); if (become_daemon) { + FILE *f = fopen("/var/run/rstpd.pid", "w"); + if (!f) { + ERROR("can't open /var/run/rstp.pid"); + return -1; + } openlog("rstpd", 0, LOG_DAEMON); daemon(0, 0); is_daemon = 1; + fprintf(f, "%d", getpid()); + fclose(f); } return epoll_main_loop(); } diff --git a/packet.c b/packet.c index aadf58c..001f6d4 100644 --- a/packet.c +++ b/packet.c @@ -48,7 +48,7 @@ static struct epoll_event_handler packet_event; -#ifdef STP_DBG +#ifdef PACKET_DEBUG static void dump_packet(const unsigned char *buf, int cc) { int i, j; @@ -76,14 +76,17 @@ void packet_send(int ifindex, const unsigned char *data, int len) .sll_halen = ETH_ALEN, }; - memcpy(sl.sll_addr, data, ETH_ALEN); + memcpy(&sl.sll_addr, data, ETH_ALEN); -#ifdef STP_DBG - printf("Send to %02x:%02x:%02x:%02x:%02x:%02x\n", +#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); #endif + l = sendto(packet_event.fd, data, len, 0, (struct sockaddr *) &sl, sizeof(sl)); @@ -101,16 +104,17 @@ static void packet_rcv(uint32_t events, struct epoll_event_handler *h) struct sockaddr_ll sl; socklen_t salen = sizeof sl; - cc = recvfrom(h->fd, &buf, sizeof(buf), 0, - (struct sockaddr *) &sl, &salen); + cc = recvfrom(h->fd, &buf, sizeof(buf), 0, (struct sockaddr *) &sl, &salen); if (cc <= 0) { ERROR("recvfrom failed: %m"); return; } -#ifdef STP_DBG - printf("Receive Src %02x:%02x:%02x:%02x:%02x:%02x\n", - buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]); +#ifdef PACKET_DEBUG + printf("Receive Src ifindex %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(buf, cc); #endif diff --git a/rstplib/Makefile b/rstplib/Makefile index c282756..1ecf211 100644 --- a/rstplib/Makefile +++ b/rstplib/Makefile @@ -21,9 +21,9 @@ #**********************************************************************/ DEFS= -CC = gcc #-E -#CFLAGS = -g -Wall -D_REENTRANT -D__LINUX__ -DSTP_DBG=1 -DOLD_READLINE -CFLAGS = -g -Wall -D_REENTRANT -D__LINUX__ -DSTP_DBG=1 # -DOLD_READLINE +CC = gcc +#CFLAGS = -g -Wall -D_REENTRANT -D__LINUX__ -DSTP_DBG=1 +CFLAGS = -g -O -Wall -D_REENTRANT -D__LINUX__ INCLUDES = -I. COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CFLAGS) -- 2.39.2