X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/d1ecb069dfe24481e4a83f44cb5217a2b06746d7..4d15aeb193b2c68f1d38666c317f8d3734f5f083:/bsd/net/if_bond.c diff --git a/bsd/net/if_bond.c b/bsd/net/if_bond.c index fa07935a6..34f6e03d4 100644 --- a/bsd/net/if_bond.c +++ b/bsd/net/if_bond.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2010 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2004-2014 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -79,8 +79,6 @@ #include #include -extern void dlil_input_packet_list(struct ifnet *, struct mbuf *); - static struct ether_addr slow_proto_multicast = { IEEE8023AD_SLOW_PROTO_MULTICAST }; @@ -304,26 +302,6 @@ struct bondport_s { static int bond_get_status(ifbond_ref ifb, struct if_bond_req * ibr_p, user_addr_t datap); -static __inline__ int -ifbond_flags_promisc(ifbond_ref ifb) -{ - return ((ifb->ifb_flags & IFBF_PROMISC) != 0); -} - -static __inline__ void -ifbond_flags_set_promisc(ifbond_ref ifb) -{ - ifb->ifb_flags |= IFBF_PROMISC; - return; -} - -static __inline__ void -ifbond_flags_clear_promisc(ifbond_ref ifb) -{ - ifb->ifb_flags &= ~IFBF_PROMISC; - return; -} - static __inline__ int ifbond_flags_if_detaching(ifbond_ref ifb) { @@ -343,20 +321,6 @@ ifbond_flags_lladdr(ifbond_ref ifb) return ((ifb->ifb_flags & IFBF_LLADDR) != 0); } -static __inline__ void -ifbond_flags_set_lladdr(ifbond_ref ifb) -{ - ifb->ifb_flags |= IFBF_LLADDR; - return; -} - -static __inline__ void -ifbond_flags_clear_lladdr(ifbond_ref ifb) -{ - ifb->ifb_flags &= ~IFBF_LLADDR; - return; -} - static __inline__ int ifbond_flags_change_in_progress(ifbond_ref ifb) { @@ -514,11 +478,15 @@ packet_buffer_allocate(int length) /* leave room for ethernet header */ size = length + sizeof(struct ether_header); if (size > (int)MHLEN) { - /* XXX doesn't handle large payloads */ - printf("bond: packet_buffer_allocate size %d > max %u\n", size, MHLEN); - return (NULL); + if (size > (int)MCLBYTES) { + printf("bond: packet_buffer_allocate size %d > max %u\n", + size, MCLBYTES); + return (NULL); + } + m = m_getcl(M_WAITOK, MT_DATA, M_PKTHDR); + } else { + m = m_gethdr(M_WAITOK, MT_DATA); } - m = m_gethdr(M_WAITOK, MT_DATA); if (m == NULL) { return (NULL); } @@ -724,8 +692,9 @@ ifbond_release(ifbond_ref ifb) printf("ifbond_release(%s) removing multicast\n", ifb->ifb_name); } - (void)if_delmultiaddr(ifb->ifb_ifma_slow_proto, 0); - ifma_release(ifb->ifb_ifma_slow_proto); + (void) if_delmulti_anon(ifb->ifb_ifma_slow_proto->ifma_ifp, + ifb->ifb_ifma_slow_proto->ifma_addr); + IFMA_REMREF(ifb->ifb_ifma_slow_proto); } if (ifb->ifb_distributing_array != NULL) { FREE(ifb->ifb_distributing_array, M_BOND); @@ -832,6 +801,10 @@ link_speed(int active) case IFM_10G_SR: case IFM_10G_LR: return (10000); + case IFM_2500_T: + return (2500); + case IFM_5000_T: + return (5000); } } @@ -885,10 +858,6 @@ if_siflladdr(struct ifnet * ifp, const struct ether_addr * ea_p) ifr.ifr_addr.sa_family = AF_UNSPEC; ifr.ifr_addr.sa_len = ETHER_ADDR_LEN; ether_addr_copy(ifr.ifr_addr.sa_data, ea_p); -#if 0 - snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s%d", ifnet_name(ifp), - ifnet_unit(ifp)); -#endif return (ifnet_ioctl(ifp, 0, SIOCSIFLLADDR, &ifr)); } @@ -901,17 +870,13 @@ bond_globals_create(lacp_system_priority sys_pri, { bond_globals_ref b; - b = _MALLOC(sizeof(*b), M_BOND, M_WAITOK); + b = _MALLOC(sizeof(*b), M_BOND, M_WAITOK | M_ZERO); if (b == NULL) { return (NULL); } - bzero(b, sizeof(*b)); TAILQ_INIT(&b->ifbond_list); b->system = *sys; b->system_priority = sys_pri; -#if 0 - b->verbose = 1; -#endif return (b); } @@ -936,7 +901,6 @@ bond_globals_init(void) for (i = 0; i < 4; i++) { char ifname[IFNAMSIZ+1]; snprintf(ifname, sizeof(ifname), "en%d", i); - /* XXX ifunit() needs to return a reference on the ifp */ ifp = ifunit(ifname); if (ifp != NULL) { break; @@ -944,7 +908,7 @@ bond_globals_init(void) } b = NULL; if (ifp != NULL) { - b = bond_globals_create(0x8000, (lacp_system_ref)ifnet_lladdr(ifp)); + b = bond_globals_create(0x8000, (lacp_system_ref)IF_LLADDR(ifp)); } bond_lock(); if (g_bond != NULL) { @@ -1108,8 +1072,7 @@ ifbond_add_slow_proto_multicast(ifbond_ref ifb) sdl.sdl_nlen = 0; sdl.sdl_alen = sizeof(slow_proto_multicast); bcopy(&slow_proto_multicast, sdl.sdl_data, sizeof(slow_proto_multicast)); - error = if_addmulti(ifb->ifb_ifp, (struct sockaddr *)&sdl, - &ifma); + error = if_addmulti_anon(ifb->ifb_ifp, (struct sockaddr *)&sdl, &ifma); if (error == 0) { ifb->ifb_ifma_slow_proto = ifma; } @@ -1122,18 +1085,17 @@ bond_clone_create(struct if_clone * ifc, u_int32_t unit, __unused void *params) int error; ifbond_ref ifb; ifnet_t ifp; - struct ifnet_init_params bond_init; + struct ifnet_init_eparams bond_init; error = bond_globals_init(); if (error != 0) { return (error); } - ifb = _MALLOC(sizeof(ifbond), M_BOND, M_WAITOK); + ifb = _MALLOC(sizeof(ifbond), M_BOND, M_WAITOK | M_ZERO); if (ifb == NULL) { return (ENOMEM); } - bzero(ifb, sizeof(*ifb)); ifbond_retain(ifb); TAILQ_INIT(&ifb->ifb_port_list); @@ -1148,6 +1110,9 @@ bond_clone_create(struct if_clone * ifc, u_int32_t unit, __unused void *params) } bzero(&bond_init, sizeof(bond_init)); + bond_init.ver = IFNET_INIT_CURRENT_VERSION; + bond_init.len = sizeof (bond_init); + bond_init.flags = IFNET_INIT_LEGACY; bond_init.uniqueid = ifb->ifb_name; bond_init.uniqueid_len = strlen(ifb->ifb_name); bond_init.name = ifc->ifc_name; @@ -1159,14 +1124,14 @@ bond_clone_create(struct if_clone * ifc, u_int32_t unit, __unused void *params) bond_init.add_proto = ether_add_proto; bond_init.del_proto = ether_del_proto; bond_init.check_multi = ether_check_multi; - bond_init.framer = ether_frameout; + bond_init.framer_extended = ether_frameout_extended; bond_init.ioctl = bond_ioctl; bond_init.set_bpf_tap = bond_set_bpf_tap; bond_init.detach = bond_if_free; bond_init.broadcast_addr = etherbroadcastaddr; bond_init.broadcast_len = ETHER_ADDR_LEN; bond_init.softc = ifb; - error = ifnet_allocate(&bond_init, &ifp); + error = ifnet_allocate_extended(&bond_init, &ifp); if (error) { ifbond_release(ifb); @@ -1236,10 +1201,10 @@ bond_if_detach(struct ifnet * ifp) int error; error = ifnet_detach(ifp); - if (error) { - printf("bond_if_detach %s%d: ifnet_detach failed, %d\n", - ifnet_name(ifp), ifnet_unit(ifp), error); - } + if (error) { + printf("bond_if_detach %s%d: ifnet_detach failed, %d\n", + ifnet_name(ifp), ifnet_unit(ifp), error); + } return; } @@ -1480,6 +1445,8 @@ bond_output(struct ifnet * ifp, struct mbuf * m) uint32_t h; ifbond_ref ifb; struct ifnet * port_ifp = NULL; + int err; + struct flowadv adv = { FADV_SUCCESS }; if (m == 0) { return (0); @@ -1488,8 +1455,8 @@ bond_output(struct ifnet * ifp, struct mbuf * m) m_freem(m); return (0); } - if (m->m_pkthdr.socket_id != 0) { - h = m->m_pkthdr.socket_id; + if (m->m_pkthdr.pkt_flowid != 0) { + h = m->m_pkthdr.pkt_flowid; } else { struct ether_header * eh_p; @@ -1527,7 +1494,17 @@ bond_output(struct ifnet * ifp, struct mbuf * m) } bond_bpf_output(ifp, m, bpf_func); - return (ifnet_output_raw(port_ifp, PF_BOND, m)); + err = dlil_output(port_ifp, PF_BOND, m, NULL, NULL, 1, &adv); + + if (err == 0) { + if (adv.code == FADV_FLOW_CONTROLLED) { + err = EQFULL; + } else if (adv.code == FADV_SUSPENDED) { + err = EQSUSPENDED; + } + } + + return (err); done: bond_unlock(); @@ -1737,7 +1714,7 @@ bond_input(ifnet_t port_ifp, __unused protocol_family_t protocol, mbuf_t m, } m->m_pkthdr.rcvif = ifp; bond_bpf_input(ifp, m, eh_p, bpf_func); - m->m_pkthdr.header = frame_header; + m->m_pkthdr.pkt_hdr = frame_header; dlil_input_packet_list(ifp, m); return 0; @@ -1843,12 +1820,11 @@ bondport_create(struct ifnet * port_ifp, lacp_port_priority priority, lacp_actor_partner_state s; *ret_error = 0; - p = _MALLOC(sizeof(*p), M_BOND, M_WAITOK); + p = _MALLOC(sizeof(*p), M_BOND, M_WAITOK | M_ZERO); if (p == NULL) { *ret_error = ENOMEM; return (NULL); } - bzero(p, sizeof(*p)); multicast_list_init(&p->po_multicast); if ((u_int32_t)snprintf(p->po_name, sizeof(p->po_name), "%s%d", ifnet_name(port_ifp), ifnet_unit(port_ifp)) @@ -2065,7 +2041,7 @@ bond_add_interface(struct ifnet * ifp, struct ifnet * port_ifp) p->po_bond = ifb; /* remember the port's ethernet address so it can be restored */ - ether_addr_copy(&p->po_saved_addr, ifnet_lladdr(port_ifp)); + 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); @@ -2080,7 +2056,7 @@ bond_add_interface(struct ifnet * ifp, struct ifnet * port_ifp) /* first port added to bond determines bond's ethernet address */ if (first) { - ifnet_set_lladdr_and_type(ifp, ifnet_lladdr(port_ifp), ETHER_ADDR_LEN, + ifnet_set_lladdr_and_type(ifp, IF_LLADDR(port_ifp), ETHER_ADDR_LEN, IFT_ETHER); } @@ -2133,7 +2109,7 @@ bond_add_interface(struct ifnet * ifp, struct ifnet * port_ifp) /* re-program the port's ethernet address */ error = if_siflladdr(port_ifp, - (const struct ether_addr *)ifnet_lladdr(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", @@ -2301,7 +2277,7 @@ bond_remove_interface(ifbond_ref ifb, struct ifnet * port_ifp) ifnet_set_mtu(ifp, 0); ifb->ifb_altmtu = 0; } else if (ifbond_flags_lladdr(ifb) == FALSE - && bcmp(&p->po_saved_addr, ifnet_lladdr(ifp), + && bcmp(&p->po_saved_addr, IF_LLADDR(ifp), ETHER_ADDR_LEN) == 0) { new_link_address = TRUE; } @@ -2344,7 +2320,7 @@ bond_remove_interface(ifbond_ref ifb, struct ifnet * port_ifp) scan_ifp = scan_port->po_ifp; error = if_siflladdr(scan_ifp, - (const struct ether_addr *) ifnet_lladdr(ifp)); + (const struct ether_addr *) IF_LLADDR(ifp)); if (error != 0) { printf("bond_remove_interface(%s, %s): " "if_siflladdr (%s) failed %d\n", @@ -2530,7 +2506,7 @@ bond_get_status(ifbond_ref ifb, struct if_bond_req * ibr_p, user_addr_t datap) break; } bzero(&ibs, sizeof(ibs)); - strncpy(ibs.ibs_if_name, port->po_name, sizeof(ibs.ibs_if_name)); + strlcpy(ibs.ibs_if_name, port->po_name, sizeof(ibs.ibs_if_name)); ibs.ibs_port_priority = port->po_priority; if (ifb->ifb_mode == IF_BOND_MODE_LACP) { ibs.ibs_state = port->po_actor_state; @@ -2571,24 +2547,6 @@ static int bond_set_promisc(__unused struct ifnet *ifp) { int error = 0; -#if 0 - ifbond_ref ifb = ifnet_softc(ifp); - - - if ((ifnet_flags(ifp) & IFF_PROMISC) != 0) { - if ((ifb->ifb_flags & IFBF_PROMISC) == 0) { - error = ifnet_set_promiscuous(ifb->ifb_p, 1); - if (error == 0) - ifb->ifb_flags |= IFBF_PROMISC; - } - } else { - if ((ifb->ifb_flags & IFBF_PROMISC) != 0) { - error = ifnet_set_promiscuous(ifb->ifb_p, 0); - if (error == 0) - ifb->ifb_flags &= ~IFBF_PROMISC; - } - } -#endif return (error); } @@ -2812,7 +2770,6 @@ bond_ioctl(struct ifnet *ifp, u_long cmd, void * data) switch (ibr.ibr_op) { case IF_BOND_OP_ADD_INTERFACE: case IF_BOND_OP_REMOVE_INTERFACE: - /* XXX ifunit() needs to return a reference on the ifp */ port_ifp = ifunit(ibr.ibr_ibru.ibru_if_name); if (port_ifp == NULL) { error = ENXIO; @@ -2947,23 +2904,16 @@ bond_if_free(struct ifnet * ifp) } static void -bond_event(struct ifnet * port_ifp, __unused protocol_family_t protocol, - const struct kev_msg * event) +bond_handle_event(struct ifnet * port_ifp, int event_code) { struct ifnet * bond_ifp = NULL; - int event_code = 0; ifbond_ref ifb; int old_distributing_count; bondport_ref p; struct media_info media_info = { 0, 0}; - if (event->vendor_code != KEV_VENDOR_APPLE - || event->kev_class != KEV_NETWORK_CLASS - || event->kev_subclass != KEV_DL_SUBCLASS) { - return; - } - switch (event->event_code) { - case KEV_DL_IF_DETACHING: + switch (event_code) { + case KEV_DL_IF_DETACHED: break; case KEV_DL_LINK_OFF: case KEV_DL_LINK_ON: @@ -2980,8 +2930,8 @@ bond_event(struct ifnet * port_ifp, __unused protocol_family_t protocol, } ifb = p->po_bond; old_distributing_count = ifb->ifb_distributing_count; - switch (event->event_code) { - case KEV_DL_IF_DETACHING: + switch (event_code) { + case KEV_DL_IF_DETACHED: bond_remove_interface(ifb, p->po_ifp); break; case KEV_DL_LINK_OFF: @@ -3042,6 +2992,37 @@ bond_event(struct ifnet * port_ifp, __unused protocol_family_t protocol, return; } +static void +bond_event(struct ifnet * port_ifp, __unused protocol_family_t protocol, + const struct kev_msg * event) +{ + int event_code; + + if (event->vendor_code != KEV_VENDOR_APPLE + || event->kev_class != KEV_NETWORK_CLASS + || event->kev_subclass != KEV_DL_SUBCLASS) { + return; + } + event_code = event->event_code; + switch (event_code) { + case KEV_DL_LINK_OFF: + case KEV_DL_LINK_ON: + /* we only care about link status changes */ + bond_handle_event(port_ifp, event_code); + break; + default: + break; + } + return; +} + +static errno_t +bond_detached(ifnet_t port_ifp, __unused protocol_family_t protocol) +{ + bond_handle_event(port_ifp, KEV_DL_IF_DETACHED); + return (0); +} + static void interface_link_event(struct ifnet * ifp, u_int32_t event_code) { @@ -3051,6 +3032,7 @@ interface_link_event(struct ifnet * ifp, u_int32_t event_code) char if_name[IFNAMSIZ]; } event; + bzero(&event, sizeof(event)); event.header.total_size = sizeof(event); event.header.vendor_code = KEV_VENDOR_APPLE; event.header.kev_class = KEV_NETWORK_CLASS; @@ -3058,7 +3040,7 @@ interface_link_event(struct ifnet * ifp, u_int32_t event_code) event.header.event_code = event_code; event.header.event_data[0] = ifnet_family(ifp); event.unit = (u_int32_t) ifnet_unit(ifp); - strncpy(event.if_name, ifnet_name(ifp), IFNAMSIZ); + strlcpy(event.if_name, ifnet_name(ifp), IFNAMSIZ); ifnet_event(ifp, &event.header); return; } @@ -3082,6 +3064,7 @@ bond_attach_protocol(struct ifnet *ifp) bzero(®, sizeof(reg)); reg.input = bond_input; reg.event = bond_event; + reg.detached = bond_detached; error = ifnet_attach_protocol(ifp, PF_BOND, ®); if (error) { @@ -3141,16 +3124,6 @@ bond_family_init(void) error); goto done; } -#endif -#if NETAT - error = proto_register_plumber(PF_APPLETALK, APPLE_IF_FAM_BOND, - ether_attach_at, - ether_detach_at); - if (error != 0) { - printf("bond: proto_register_plumber failed for AppleTalk error=%d\n", - error); - goto done; - } #endif error = bond_clone_attach(); if (error != 0) {