]> git.ipfire.org Git - people/ms/rstp.git/blobdiff - bridge_track.c
Make local functions static
[people/ms/rstp.git] / bridge_track.c
index bf4a2da176e8b937738efc9bd251a11e895dbd37..efc23e5522de937b955e1856336d8a6eb06d1970 100644 (file)
 
 #include "bridge_ctl.h"
 #include "netif_utils.h"
+#include "packet.h"
 
 #include <unistd.h>
 #include <net/if.h>
+#include <stdlib.h>
 #include <linux/if_bridge.h>
 #include <arpa/inet.h>
 #include <sys/types.h>
@@ -80,6 +82,8 @@ struct ifdata {
        ADMIN_P2P_T admin_point2point;
        unsigned char admin_edge;
        unsigned char admin_non_stp;    /* 1- doesn't participate in STP, 1 - regular */
+
+       struct epoll_event_handler event;
 };
 
 /* Instances */
@@ -162,8 +166,6 @@ void update_port_stp_config(struct ifdata *ifc, UID_STP_PORT_CFG_T * cfg)
 
 int add_port_stp(struct ifdata *ifc)
 {                              /* Bridge is ifc->master */
-       char name[IFNAMSIZ];
-       TST(if_indextoname(ifc->if_index, name) != 0, -1);
        TST((ifc->port_index = get_bridge_portno(ifc->name)) >= 0, -1);
 
        /* Add port to STP */
@@ -311,11 +313,15 @@ struct ifdata *create_if(int if_index, struct ifdata *br)
        struct ifdata *p;
        TST((p = malloc(sizeof(*p))) != NULL, NULL);
 
+       memset(p, 0, sizeof(*p));
+
        /* Init fields */
        p->if_index = if_index;
        p->is_bridge = (br == NULL);
-       memset(p->name, 0, sizeof(p->name));
+
+       /* TODO: purge use of name, due to issue with renameing */
        if_indextoname(if_index, p->name);
+
        if (p->is_bridge) {
                INFO("Add bridge %s", p->name);
                /* Init slave list */
@@ -333,12 +339,15 @@ struct ifdata *create_if(int if_index, struct ifdata *br)
                p->speed = 0;
                p->duplex = 0;
                p->master = br;
+
                update_port_stp_config(p, &default_port_stp_cfg);
                ADD_TO_LIST(br->port_list, port_next, p);       /* Add to bridge port list */
+
                if (br->stp_up) {
                        add_port_stp(p);
                }
        }
+
        /* Add to interface list */
        ADD_TO_LIST(if_head, next, p);
 
@@ -366,22 +375,58 @@ void delete_if(struct ifdata *ifc)
                                 "Can't find interface ifindex %d on br %d's port list",
                                 ifc->if_index, ifc->master->if_index);
        }
+
        /* Remove from bridge interface list */
        REMOVE_FROM_LIST(if_head, next, ifc,
                         "Can't find interface ifindex %d on iflist",
                         ifc->if_index);
+       free(ifc);
 }
 
-void set_br_up(struct ifdata *br, int up)
+static int stp_enabled(struct ifdata *br)
 {
-       if (up != br->up) {
+       char path[40 + IFNAMSIZ];
+       int ret;
+       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;
+       ret = fscanf(f, "%d", &enabled);
+       if (!ret) {
+               LOG("%s, stp_state parsing error", path);
+               return 0;
+       }
+       fclose(f);
+       INFO("STP on %s state %d", br->name, enabled);
+
+       return enabled == 2;    /* ie user mode STP */
+}
+
+static void set_br_up(struct ifdata *br, int 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);
        }
 }
 
-void set_if_up(struct ifdata *ifc, int up)
+static void set_if_up(struct ifdata *ifc, int up)
 {
        INFO("Port %s : %s", ifc->name, (up ? "up" : "down"));
        int speed = -1;
@@ -533,19 +578,22 @@ 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)
 {
-       LOG("ifindex %d, len %d", if_index, len);
        struct ifdata *ifc = find_if(if_index);
-       TST(ifc && !ifc->is_bridge,);
-       TST(ifc->up && ifc->master->stp_up,);
-       BPDU_T bpdu;
-       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);
+       BPDU_T *bpdu = (BPDU_T *) (data + sizeof(MAC_HEADER_T));
+
+       LOG("ifindex %d, len %d", if_index, len);
+       if (!ifc || !ifc->master)
+               return;
+
+       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:
@@ -553,20 +601,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));
@@ -721,9 +769,9 @@ 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)));
-       bridge_send_bpdu(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(MAC_HEADER_T) + sizeof(ETH_HEADER_T));
        return 0;
 }