]> git.ipfire.org Git - people/ms/mstpd.git/blobdiff - bridge_track.c
Translate CIST states to the Linux bridge code
[people/ms/mstpd.git] / bridge_track.c
index 044fea195cbf1bdb0599bcf77a1ec8c178b441b7..ae22c6906ac70198c6771a98f5ac0869253f5eef 100644 (file)
@@ -34,6 +34,8 @@
 #include "packet.h"
 #include "log.h"
 #include "mstp.h"
+#include "driver.h"
+#include "libnetlink.h"
 
 static LIST_HEAD(bridges);
 
@@ -431,6 +433,28 @@ void bridge_bpdu_rcv(int if_index, const unsigned char *data, int len)
                     (bpdu_t *)(data + sizeof(*h)), l - LLC_PDU_LEN_U);
 }
 
+static int br_set_state(struct rtnl_handle *rth, unsigned ifindex, __u8 state)
+{
+    struct
+    {
+        struct nlmsghdr n;
+        struct ifinfomsg ifi;
+        char buf[256];
+    } req;
+
+    memset(&req, 0, sizeof(req));
+
+    req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
+    req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_REPLACE;
+    req.n.nlmsg_type = RTM_SETLINK;
+    req.ifi.ifi_family = AF_BRIDGE;
+    req.ifi.ifi_index = ifindex;
+
+    addattr8(&req.n, sizeof(req.buf), IFLA_PROTINFO, state);
+
+    return rtnl_talk(rth, &req.n, 0, 0, NULL, NULL, NULL);
+}
+
 /* External actions for MSTP protocol */
 
 void MSTP_OUT_set_state(per_tree_port_t *ptp, int new_state)
@@ -439,7 +463,11 @@ void MSTP_OUT_set_state(per_tree_port_t *ptp, int new_state)
     port_t *ifc = ptp->port;
     bridge_t *br = ifc->bridge;
 
-    switch(new_state)
+    if(ptp->state == new_state)
+        return;
+    ptp->state = driver_set_new_state(ptp, new_state);
+
+    switch(ptp->state)
     {
         case BR_STATE_LISTENING:
             state_name = "listening";
@@ -454,21 +482,22 @@ void MSTP_OUT_set_state(per_tree_port_t *ptp, int new_state)
             state_name = "blocking";
             break;
         default:
-            ERROR_MSTINAME(br, ifc, ptp, "attempt to set invalid state %d",
-                           new_state);
-            new_state = BR_STATE_DISABLED;
         case BR_STATE_DISABLED:
             state_name = "disabled";
             break;
     }
-
-    if(ptp->state == new_state)
-        return;
-
-    /* TODO: command driver to put the br:port:tree into new state */
-
-    ptp->state = new_state;
     INFO_MSTINAME(br, ifc, ptp, "entering %s state", state_name);
+
+    /* Translate new CIST state to the kernel bridge code */
+    if(0 == ptp->MSTID)
+    { /* CIST */
+        if(ifc->sysdeps.up)
+        {
+            if(0 > br_set_state(&rth_state, ifc->sysdeps.if_index, ptp->state))
+                ERROR_PRTNAME(br, ifc, "Couldn't set kernel bridge state %s",
+                              state_name);
+        }
+    }
 }
 
 /* This function initiates process of flushing