Lines 102-107
Link Here
|
102 |
static int lagg_port_checkstacking(struct lagg_softc *); |
102 |
static int lagg_port_checkstacking(struct lagg_softc *); |
103 |
#endif |
103 |
#endif |
104 |
static void lagg_port2req(struct lagg_port *, struct lagg_reqport *); |
104 |
static void lagg_port2req(struct lagg_port *, struct lagg_reqport *); |
|
|
105 |
static void lagg_if_updown(struct lagg_softc *, int); |
105 |
static void lagg_init(void *); |
106 |
static void lagg_init(void *); |
106 |
static void lagg_stop(struct lagg_softc *); |
107 |
static void lagg_stop(struct lagg_softc *); |
107 |
static int lagg_ioctl(struct ifnet *, u_long, caddr_t); |
108 |
static int lagg_ioctl(struct ifnet *, u_long, caddr_t); |
Lines 589-594
Link Here
|
589 |
/* Insert into the list of ports */ |
590 |
/* Insert into the list of ports */ |
590 |
SLIST_INSERT_HEAD(&sc->sc_ports, lp, lp_entries); |
591 |
SLIST_INSERT_HEAD(&sc->sc_ports, lp, lp_entries); |
591 |
sc->sc_count++; |
592 |
sc->sc_count++; |
|
|
593 |
sc->sc_generation++; |
592 |
|
594 |
|
593 |
/* Update lagg capabilities */ |
595 |
/* Update lagg capabilities */ |
594 |
lagg_capabilities(sc); |
596 |
lagg_capabilities(sc); |
Lines 662-667
Link Here
|
662 |
/* Finally, remove the port from the lagg */ |
664 |
/* Finally, remove the port from the lagg */ |
663 |
SLIST_REMOVE(&sc->sc_ports, lp, lagg_port, lp_entries); |
665 |
SLIST_REMOVE(&sc->sc_ports, lp, lagg_port, lp_entries); |
664 |
sc->sc_count--; |
666 |
sc->sc_count--; |
|
|
667 |
sc->sc_generation++; |
665 |
|
668 |
|
666 |
/* Update the primary interface */ |
669 |
/* Update the primary interface */ |
667 |
if (lp == sc->sc_primary) { |
670 |
if (lp == sc->sc_primary) { |
Lines 753-759
Link Here
|
753 |
break; |
756 |
break; |
754 |
|
757 |
|
755 |
case SIOCSIFMTU: |
758 |
case SIOCSIFMTU: |
756 |
/* Do not allow the MTU to be changed once joined */ |
759 |
/* |
|
|
760 |
* We don't allow changing the MTU on a per-port basis once |
761 |
* the port is part of a lagg. The user must change the |
762 |
* MTU of the lagg as a whole. |
763 |
*/ |
757 |
error = EINVAL; |
764 |
error = EINVAL; |
758 |
break; |
765 |
break; |
759 |
|
766 |
|
Lines 852-857
Link Here
|
852 |
} |
859 |
} |
853 |
|
860 |
|
854 |
static void |
861 |
static void |
|
|
862 |
lagg_if_updown(struct lagg_softc *sc, int up) |
863 |
{ |
864 |
struct lagg_port *lp; |
865 |
|
866 |
LAGG_WLOCK_ASSERT(sc); |
867 |
|
868 |
startover: |
869 |
|
870 |
SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { |
871 |
struct ifreq ifr; |
872 |
uint64_t cur_generation; |
873 |
int error; |
874 |
|
875 |
if (up != 0) |
876 |
if_up(lp->lp_ifp); |
877 |
else |
878 |
if_down(lp->lp_ifp); |
879 |
|
880 |
if (lp->lp_ioctl == NULL) |
881 |
continue; |
882 |
bzero(&ifr, sizeof(ifr)); |
883 |
|
884 |
cur_generation = sc->sc_generation; |
885 |
|
886 |
LAGG_WUNLOCK(sc); |
887 |
error = lp->lp_ioctl(lp->lp_ifp, SIOCSIFFLAGS, (caddr_t)&ifr); |
888 |
LAGG_WLOCK(sc); |
889 |
|
890 |
if (cur_generation != sc->sc_generation) |
891 |
goto startover; |
892 |
} |
893 |
} |
894 |
|
895 |
static void |
855 |
lagg_init(void *xsc) |
896 |
lagg_init(void *xsc) |
856 |
{ |
897 |
{ |
857 |
struct lagg_softc *sc = (struct lagg_softc *)xsc; |
898 |
struct lagg_softc *sc = (struct lagg_softc *)xsc; |
Lines 868-873
Link Here
|
868 |
SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) |
909 |
SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) |
869 |
lagg_port_lladdr(lp, IF_LLADDR(ifp)); |
910 |
lagg_port_lladdr(lp, IF_LLADDR(ifp)); |
870 |
|
911 |
|
|
|
912 |
lagg_if_updown(sc, /*up*/ 1); |
913 |
|
871 |
if (sc->sc_init != NULL) |
914 |
if (sc->sc_init != NULL) |
872 |
(*sc->sc_init)(sc); |
915 |
(*sc->sc_init)(sc); |
873 |
|
916 |
|
Lines 888-893
Link Here
|
888 |
|
931 |
|
889 |
if (sc->sc_stop != NULL) |
932 |
if (sc->sc_stop != NULL) |
890 |
(*sc->sc_stop)(sc); |
933 |
(*sc->sc_stop)(sc); |
|
|
934 |
|
935 |
lagg_if_updown(sc, /*up*/ 0); |
891 |
} |
936 |
} |
892 |
|
937 |
|
893 |
static int |
938 |
static int |
Lines 1096-1106
Link Here
|
1096 |
break; |
1141 |
break; |
1097 |
|
1142 |
|
1098 |
case SIOCSIFCAP: |
1143 |
case SIOCSIFCAP: |
1099 |
case SIOCSIFMTU: |
1144 |
/* Do not allow caps to be directly changed */ |
1100 |
/* Do not allow the MTU or caps to be directly changed */ |
|
|
1101 |
error = EINVAL; |
1145 |
error = EINVAL; |
1102 |
break; |
1146 |
break; |
|
|
1147 |
case SIOCSIFMTU: { |
1148 |
struct ifreq *ifr; |
1149 |
int new_mtu, old_mtu; |
1150 |
int error2 = 0; |
1151 |
|
1152 |
ifr = (struct ifreq *)data; |
1153 |
|
1154 |
new_mtu = ifr->ifr_mtu; |
1155 |
|
1156 |
old_mtu = sc->sc_ifp->if_mtu; |
1157 |
/* Nothing to do if there is no change */ |
1158 |
if (new_mtu == old_mtu) |
1159 |
break; |
1103 |
|
1160 |
|
|
|
1161 |
LAGG_WLOCK(sc); |
1162 |
SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { |
1163 |
if (lp->lp_ioctl == NULL) { |
1164 |
printf("%s: SIOCSIFMTU: unable to change " |
1165 |
"MTU for %s because it has no ioctl " |
1166 |
"routine\n", __func__, |
1167 |
lp->lp_ifp->if_xname); |
1168 |
error = EINVAL; |
1169 |
break; |
1170 |
} |
1171 |
error = lp->lp_ioctl(lp->lp_ifp, cmd, data); |
1172 |
/* |
1173 |
* If we get an error setting the MTU for this |
1174 |
* component interface, just exit, and below we'll |
1175 |
* try to reset all of the ports to the previous |
1176 |
* value. |
1177 |
*/ |
1178 |
if (error != 0) { |
1179 |
printf("%s: SIOCSIFMTU: error %d changing MTU " |
1180 |
"for %s from %d to %d\n", __func__, error, |
1181 |
lp->lp_ifp->if_xname, old_mtu, new_mtu); |
1182 |
break; |
1183 |
} |
1184 |
} |
1185 |
if (error == 0) { |
1186 |
/* We were successful, so update our saved MTU. */ |
1187 |
sc->sc_ifp->if_mtu = new_mtu; |
1188 |
LAGG_WUNLOCK(sc); |
1189 |
break; |
1190 |
} |
1191 |
/* |
1192 |
* In the error case, try to reset all of the ports to |
1193 |
* their previous value. |
1194 |
*/ |
1195 |
SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { |
1196 |
if (lp->lp_ioctl == NULL) |
1197 |
continue; |
1198 |
|
1199 |
error2 = lp->lp_ioctl(lp->lp_ifp, cmd, |
1200 |
(caddr_t)&old_mtu); |
1201 |
/* |
1202 |
* This shouldn't fail, because the port was |
1203 |
* previously at this MTU. If it does for some |
1204 |
* reason, continue on to get as many ports as |
1205 |
* possible back to the old MTU. |
1206 |
*/ |
1207 |
if (error2 != 0) { |
1208 |
printf("%s: SIOCSIFMTU: error %d changing MTU " |
1209 |
"for %s back to %d\n", __func__, error, |
1210 |
lp->lp_ifp->if_xname, old_mtu); |
1211 |
} |
1212 |
} |
1213 |
LAGG_WUNLOCK(sc); |
1214 |
break; |
1215 |
} |
1104 |
default: |
1216 |
default: |
1105 |
error = ether_ioctl(ifp, cmd, data); |
1217 |
error = ether_ioctl(ifp, cmd, data); |
1106 |
break; |
1218 |
break; |