]> git.ipfire.org Git - people/ms/rstp.git/blobdiff - bridge_track.c
Ignore carrier state on bridge device
[people/ms/rstp.git] / bridge_track.c
index fbb8288907e031e48b4a214fc8a6b9ca95764b29..289fc412497387fa2a43a8ae31af82cce2672938 100644 (file)
@@ -340,11 +340,6 @@ struct ifdata *create_if(int if_index, struct ifdata *br)
                p->duplex = 0;
                p->master = br;
 
-               if (packet_sock_create(&p->event, p->if_index, p)) {
-                       free(p);
-                       return NULL;
-               }
-
                update_port_stp_config(p, &default_port_stp_cfg);
                ADD_TO_LIST(br->port_list, port_next, p);       /* Add to bridge port list */
 
@@ -379,7 +374,6 @@ void delete_if(struct ifdata *ifc)
                REMOVE_FROM_LIST(ifc->master->port_list, port_next, ifc,
                                 "Can't find interface ifindex %d on br %d's port list",
                                 ifc->if_index, ifc->master->if_index);
-               packet_sock_delete(&ifc->event);
        }
 
        /* Remove from bridge interface list */
@@ -389,16 +383,50 @@ void delete_if(struct ifdata *ifc)
        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;
@@ -448,13 +476,14 @@ void set_if_up(struct ifdata *ifc, int up)
 
 /*------------------------------------------------------------*/
 
-int bridge_notify(int br_index, int if_index, int newlink, int up)
+int bridge_notify(int br_index, int if_index, int newlink, 
+                 unsigned flags)
 {
-       if (up)
-               up = 1;
-       LOG("br_index %d, if_index %d, up %d", br_index, if_index, up);
-
        struct ifdata *br = NULL;
+
+       LOG("br_index %d, if_index %d, up %d running %d",
+           br_index, if_index, (flags & IFF_UP), flags & IFF_RUNNING);
+
        if (br_index >= 0) {
                br = find_if(br_index);
                if (br && !br->is_bridge) {
@@ -508,6 +537,8 @@ int bridge_notify(int br_index, int if_index, int newlink, int up)
                        delete_if(ifc);
                        return 0;
                }
+               int up = (flags & (IFF_UP|IFF_RUNNING)) == (IFF_UP|IFF_RUNNING);
+
                if (ifc->up != up)
                        set_if_up(ifc, up);     /* And speed and duplex */
        } else {                /* No br_index */
@@ -537,32 +568,42 @@ int bridge_notify(int br_index, int if_index, int newlink, int up)
                                delete_if(ifc);
                                return 0;
                        }
-                       if (ifc && ifc->up != up) {
-                               if (ifc->is_bridge)
-                                       set_br_up(ifc, up);
-                               else
-                                       set_if_up(ifc, up);
+
+                       if (ifc) {
+                               if (ifc->is_bridge) {
+                                       int up = (flags & IFF_UP) != 0;
+                                       if (ifc->up != up)
+                                               set_br_up(ifc, up);
+                               } else {
+                                       int up = (flags & (IFF_UP|IFF_RUNNING)) == (IFF_UP|IFF_RUNNING);
+
+                                       if (ifc->up != up)
+                                               set_if_up(ifc, up);
+                               }
                        }
                }
        }
        return 0;
 }
 
-void bridge_bpdu_rcv(struct ifdata *ifc, const unsigned char *data, int len)
+void bridge_bpdu_rcv(int if_index, const unsigned char *data, int len)
 {
-       TST(ifc && !ifc->is_bridge,);
-       TST(ifc->up && ifc->master->stp_up,);
-       BPDU_T bpdu;
+       struct ifdata *ifc = find_if(if_index);
+       BPDU_T *bpdu = (BPDU_T *) (data + sizeof(MAC_HEADER_T));
 
-       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);
+       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:
@@ -570,20 +611,20 @@ void bridge_bpdu_rcv(struct ifdata *ifc, 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));
@@ -738,9 +779,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;
 }