- printf("if_bond: interface %s doesn't support mtu %d",
- bondport_get_name(p), devmtu);
- bondport_free(p);
- return (EINVAL);
- }
-
- /* make sure ifb doesn't get de-allocated while we wait */
- ifbond_retain(ifb);
-
- /* wait for other add or remove to complete */
- ifbond_wait(ifb, "bond_add_interface");
-
- if (ifbond_flags_if_detaching(ifb)) {
- /* someone destroyed the bond while we were waiting */
- error = EBUSY;
- goto signal_done;
- }
- if (bond_lookup_port(port_ifp) != NULL) {
- /* port is already part of a bond */
- error = EBUSY;
- goto signal_done;
- }
- ifnet_lock_exclusive(port_ifp);
- if ((ifnet_eflags(port_ifp) & (IFEF_VLAN | IFEF_BOND)) != 0) {
- /* interface already has VLAN's, or is part of bond */
- ifnet_lock_done(port_ifp);
- error = EBUSY;
- goto signal_done;
- }
-
- /* mark the interface busy */
- /* can't use ifnet_set_eflags because that takes the lock */
- port_ifp->if_eflags |= IFEF_BOND;
- ifnet_lock_done(port_ifp);
-
- if (TAILQ_EMPTY(&ifb->ifb_port_list)) {
- ifnet_set_offload(ifp, ifnet_offload(port_ifp));
- ifnet_set_flags(ifp, IFF_RUNNING, IFF_RUNNING);
- if (ifbond_flags_lladdr(ifb) == FALSE) {
- first = TRUE;
- }
- } else {
- ifnet_offload_t ifp_offload;
- ifnet_offload_t port_ifp_offload;
-
- ifp_offload = ifnet_offload(ifp);
- port_ifp_offload = ifnet_offload(port_ifp);
- if (ifp_offload != port_ifp_offload) {
- ifnet_offload_t offload;
-
- offload = ifp_offload & port_ifp_offload;
- printf("bond_add_interface(%s, %s) "
- "hwassist values don't match 0x%x != 0x%x, using 0x%x instead\n",
- ifb->ifb_name, bondport_get_name(p),
- ifp_offload, port_ifp_offload, offload);
- /*
- * XXX
- * if the bond has VLAN's, we can't simply change the hwassist
- * field behind its back: this needs work
- */
- ifnet_set_offload(ifp, offload);
- }
- }
- p->po_bond = ifb;
-
- /* remember the port's ethernet address so it can be restored */
- ether_addr_copy(&p->po_saved_addr, IF_LLADDR(port_ifp));
-
- /* add it to the list of ports */
- TAILQ_INSERT_TAIL(&ifb->ifb_port_list, p, po_port_list);
- ifb->ifb_port_count++;
-
- /* set the default MTU */
- if (ifnet_mtu(ifp) == 0) {
- ifnet_set_mtu(ifp, ETHERMTU);
- }
- bond_unlock();
-
-
- /* first port added to bond determines bond's ethernet address */
- if (first) {
- ifnet_set_lladdr_and_type(ifp, IF_LLADDR(port_ifp), ETHER_ADDR_LEN,
- IFT_ETHER);
- }
-
- progress |= BOND_ADD_PROGRESS_IN_LIST;
-
- /* allocate a larger distributing array */
- new_array = (bondport_ref *)
- _MALLOC(sizeof(*new_array) * ifb->ifb_port_count, M_BOND, M_WAITOK);
- if (new_array == NULL) {
- error = ENOMEM;
- goto failed;
- }
-
- /* attach our BOND "protocol" to the interface */
- error = bond_attach_protocol(port_ifp);
- if (error) {
- goto failed;
- }
- progress |= BOND_ADD_PROGRESS_PROTO_ATTACHED;
-
- /* set the interface MTU */
- devmtu = bond_device_mtu(ifp, ifb);
- error = siocsifmtu(port_ifp, devmtu);
- if (error != 0) {
- printf("bond_add_interface(%s, %s):"
- " SIOCSIFMTU %d failed %d\n",
- ifb->ifb_name, bondport_get_name(p), devmtu, error);
- goto failed;
- }
- progress |= BOND_ADD_PROGRESS_MTU_SET;
-
- /* program the port with our multicast addresses */
- error = multicast_list_program(&p->po_multicast, ifp, port_ifp);
- if (error) {
- printf("bond_add_interface(%s, %s):"
- " multicast_list_program failed %d\n",
- ifb->ifb_name, bondport_get_name(p), error);
- goto failed;
- }
-
- /* mark the interface up */
- ifnet_set_flags(port_ifp, IFF_UP, IFF_UP);
-
- error = ifnet_ioctl(port_ifp, 0, SIOCSIFFLAGS, NULL);
- if (error != 0) {
- printf("bond_add_interface(%s, %s): SIOCSIFFLAGS failed %d\n",
- ifb->ifb_name, bondport_get_name(p), error);
- goto failed;
- }
-
- /* re-program the port's ethernet address */
- error = if_siflladdr(port_ifp,
- (const struct ether_addr *)IF_LLADDR(ifp));
- if (error != 0) {
- /* port doesn't support setting the link address */
- printf("bond_add_interface(%s, %s): if_siflladdr failed %d\n",
- ifb->ifb_name, bondport_get_name(p), error);
- goto failed;
- }
- progress |= BOND_ADD_PROGRESS_LLADDR_SET;
-
- bond_lock();
-
- /* no failures past this point */
- p->po_enabled = 1;
-
- /* copy the contents of the existing distributing array */
- if (ifb->ifb_distributing_count) {
- bcopy(ifb->ifb_distributing_array, new_array,
- sizeof(*new_array) * ifb->ifb_distributing_count);
- }
- old_array = ifb->ifb_distributing_array;
- ifb->ifb_distributing_array = new_array;
-
- if (ifb->ifb_mode == IF_BOND_MODE_LACP) {
- bondport_start(p);