|
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; |