]> git.ipfire.org Git - people/ms/rstp.git/blobdiff - bridge_track.c
Track and cache bridge and port MAC addresses.
[people/ms/rstp.git] / bridge_track.c
index e4b512d7de500c9fb11693aba96933470132c57a..9a1ed6e97e45badb3927766ebe49485049de3f13 100644 (file)
@@ -52,6 +52,7 @@ struct ifdata {
        struct ifdata *next;
        int up;
        char name[IFNAMSIZ];
+       unsigned char macaddr[6];
 
        int is_bridge;
        /* If bridge */
@@ -322,6 +323,7 @@ struct ifdata *create_if(int if_index, struct ifdata *br)
 
        /* TODO: purge use of name, due to issue with renameing */
        if_indextoname(if_index, p->name);
+       get_hwaddr(p->name, p->macaddr);
 
        if (p->is_bridge) {
                INFO("Add bridge %s", p->name);
@@ -384,6 +386,24 @@ void delete_if(struct ifdata *ifc)
        free(ifc);
 }
 
+/* New MAC address is stored in addr, which also holds the old value on entry.
+   Return nonzero if the address changed */
+static int check_mac_address(char *name, unsigned char *addr)
+{
+       unsigned char temp_addr[6];
+       if (get_hwaddr(name, temp_addr)) {
+               /* Error. Ignore the new value */
+               return 0;
+       }
+       if (memcmp(addr, temp_addr, sizeof(temp_addr)) == 0)
+               return 0;
+       else {
+               memcpy(addr, temp_addr, sizeof(temp_addr));
+               return 1;
+       }
+}
+
+
 static int stp_enabled(struct ifdata *br)
 {
        char path[40 + IFNAMSIZ];
@@ -411,6 +431,13 @@ void set_br_up(struct ifdata *br, int up)
        if (up != br->up)
                br->up = up;
        
+       if (check_mac_address(br->name, br->macaddr)) {
+               /* MAC address changed */
+               if (br->stp_up && stp_up) {
+                       /* Notify bridge address change */
+               }
+       }
+
        if (br->stp_up != stp_up) {
                if (stp_up)
                        init_bridge_stp(br);
@@ -426,6 +453,15 @@ void set_if_up(struct ifdata *ifc, int up)
        int duplex = -1;
        int notify_flags = 0;
        const int NOTIFY_UP = 1, NOTIFY_SPEED = 2, NOTIFY_DUPLEX = 4;
+
+       if (check_mac_address(ifc->name, ifc->macaddr)) {
+               /* MAC address changed */
+               if (check_mac_address(ifc->master->name, ifc->master->macaddr)
+                       && ifc->master->stp_up) {
+                       /* Notify bridge address change */
+               }
+       }
+
        if (!up) {              /* Down */
                if (ifc->up) {
                        ifc->up = up;
@@ -492,8 +528,7 @@ int bridge_notify(int br_index, int if_index, int newlink, int up)
                        return -1;
                }
                /* Bridge must be up if we get such notifications */
-               if (!br->up)
-                       set_br_up(br, 1);
+               set_br_up(br, 1);
        }
 
        struct ifdata *ifc = find_if(if_index);
@@ -532,8 +567,7 @@ int bridge_notify(int br_index, int if_index, int newlink, int up)
                        delete_if(ifc);
                        return 0;
                }
-               if (ifc->up != up)
-                       set_if_up(ifc, up);     /* And speed and duplex */
+               set_if_up(ifc, up);     /* And speed and duplex */
        } else {                /* No br_index */
                if (!newlink) {
                        /* DELLINK not from bridge means interface unregistered. */
@@ -555,7 +589,7 @@ int bridge_notify(int br_index, int if_index, int newlink, int up)
                                        }
                                }
                        }
-                       if (ifc && ifc->up != up) {
+                       if (ifc) {
                                if (ifc->is_bridge)
                                        set_br_up(ifc, up);
                                else
@@ -720,7 +754,7 @@ void /* for bridge id calculation */ STP_OUT_get_port_mac(IN int port_index,
        LOG("port index %d", port_index);
        struct ifdata *port = find_port(port_index);
        TST(port != NULL,);
-       get_hwaddr(port->name, mac);
+       memcpy(mac, port->macaddr, sizeof(port->macaddr));
 }
 
 unsigned long STP_OUT_get_port_oper_speed(IN unsigned int port_index)