Print this page
6274 MAC tries to use aggr rings from downed links
Reviewed by: Bryan Cantrill <bryan@joyent.com>
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
Reviewed by: Dan McDonald <danmcd@omniti.com>
Approved by: Richard Lowe <richlowe@richlowe.net>

@@ -18,10 +18,11 @@
  *
  * CDDL HEADER END
  */
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2015 Joyent, Inc.
  */
 
 /*
  * IEEE 802.3ad Link Aggregation -- Link Aggregation Groups.
  *

@@ -570,10 +571,42 @@
 
         return (0);
 }
 
 /*
+ * This is called in response to either our LACP state machine or a MAC
+ * notification that the link has gone down via aggr_send_port_disable(). At
+ * this point, we may need to update our default ring. To that end, we go
+ * through the set of ports (underlying datalinks in an aggregation) that are
+ * currently enabled to transmit data. If all our links have been disabled for
+ * transmit, then we don't do anything.
+ *
+ * Note, because we only have a single TX group, we don't have to worry about
+ * the rings moving between groups and the chance that mac will reassign it
+ * unless someone removes a port, at which point, we play it safe and call this
+ * again.
+ */
+void
+aggr_grp_update_default(aggr_grp_t *grp)
+{
+        aggr_port_t *port;
+        ASSERT(MAC_PERIM_HELD(grp->lg_mh));
+
+        rw_enter(&grp->lg_tx_lock, RW_WRITER);
+
+        if (grp->lg_ntx_ports == 0) {
+                rw_exit(&grp->lg_tx_lock);
+                return;
+        }
+
+        port = grp->lg_tx_ports[0];
+        ASSERT(port->lp_tx_ring_cnt > 0);
+        mac_hwring_set_default(grp->lg_mh, port->lp_pseudo_tx_rings[0]);
+        rw_exit(&grp->lg_tx_lock);
+}
+
+/*
  * Add a pseudo RX ring for the given HW ring handle.
  */
 static int
 aggr_add_pseudo_rx_ring(aggr_port_t *port,
     aggr_pseudo_rx_group_t *rx_grp, mac_ring_handle_t hw_rh)

@@ -815,10 +848,11 @@
                 if (hw_rh != NULL) {
                         mac_hwring_setup(hw_rh, (mac_resource_handle_t)ring,
                             mac_find_ring(tx_grp->atg_gh, i));
                 }
         }
+
         return (err);
 }
 
 /*
  * Remove the pseudo TX ring of the given HW ring handle.

@@ -917,10 +951,11 @@
                 port->lp_tx_grp_added = B_TRUE;
                 port->lp_tx_notify_mh = mac_client_tx_notify(port->lp_mch,
                     aggr_tx_ring_update, port);
         }
         mac_perim_exit(pmph);
+        aggr_grp_update_default(grp);
         return (err);
 }
 
 /*
  * This function is called by aggr to remove pseudo TX rings over the

@@ -950,10 +985,11 @@
             (sizeof (mac_ring_handle_t *) * port->lp_tx_ring_cnt));
 
         port->lp_tx_ring_cnt = 0;
         (void) mac_client_tx_notify(port->lp_mch, NULL, port->lp_tx_notify_mh);
         port->lp_tx_grp_added = B_FALSE;
+        aggr_grp_update_default(grp);
 done:
         mac_perim_exit(pmph);
 }
 
 static int