/*
- * Copyright (c) 2004-2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2004-2014 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
#include <net/if_media.h>
#include <net/multicast_list.h>
-extern void dlil_input_packet_list(struct ifnet *, struct mbuf *);
-
static struct ether_addr slow_proto_multicast = {
IEEE8023AD_SLOW_PROTO_MULTICAST
};
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)
{
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)
{
/* 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 %lu\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);
}
/**
** bond interface/dlil specific routines
**/
-static int bond_clone_create(struct if_clone *, int);
-static void bond_clone_destroy(struct ifnet *);
+static int bond_clone_create(struct if_clone *, u_int32_t, void *);
+static int bond_clone_destroy(struct ifnet *);
static int bond_input(ifnet_t ifp, protocol_family_t protocol, mbuf_t m,
char *frame_header);
static int bond_output(struct ifnet *ifp, struct mbuf *m);
-static int bond_ioctl(struct ifnet *ifp, u_int32_t cmd, void * addr);
+static int bond_ioctl(struct ifnet *ifp, u_long cmd, void * addr);
static int bond_set_bpf_tap(struct ifnet * ifp, bpf_tap_mode mode,
bpf_packet_func func);
static int bond_attach_protocol(struct ifnet *ifp);
bond_clone_destroy,
0,
BOND_MAXUNIT);
-static void interface_link_event(struct ifnet * ifp, u_long event_code);
+static void interface_link_event(struct ifnet * ifp, u_int32_t event_code);
static int
siocsifmtu(struct ifnet * ifp, int mtu)
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);
case IFM_10G_SR:
case IFM_10G_LR:
return (10000);
+ case IFM_2500_T:
+ return (2500);
+ case IFM_5000_T:
+ return (5000);
}
}
return (mi);
}
-/**
- ** interface utility functions
- **/
-static __inline__ struct ifaddr *
-ifindex_get_ifaddr(int i)
-{
- if (i > if_index || i == 0) {
- return (NULL);
- }
- return (ifnet_addrs[i - 1]);
-}
-
-static __inline__ struct ifaddr *
-ifp_get_ifaddr(struct ifnet * ifp)
-{
- return (ifindex_get_ifaddr(ifnet_index(ifp)));
-}
-
-static __inline__ struct sockaddr_dl *
-ifp_get_sdl(struct ifnet * ifp)
-{
- struct ifaddr * ifa;
-
- ifa = ifp_get_ifaddr(ifp);
- return ((struct sockaddr_dl *)(ifa->ifa_addr));
-}
-
static int
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 0
return (ifnet_ioctl(ifp, 0, SIOCSIFLLADDR, &ifr));
}
{
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 0
return (b);
}
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;
}
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) {
return (result);
}
-static void
+static int
bond_clone_attach(void)
{
- if_clone_attach(&bond_cloner);
+ int error;
+
+ if ((error = if_clone_attach(&bond_cloner)) != 0)
+ return error;
bond_lock_init();
- return;
+ return 0;
}
static int
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;
}
}
static int
-bond_clone_create(struct if_clone * ifc, int unit)
+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);
ifb->ifb_key = unit + 1;
/* use the interface name as the unique id for ifp recycle */
- if ((u_long)snprintf(ifb->ifb_name, sizeof(ifb->ifb_name), "%s%d",
+ if ((u_int32_t)snprintf(ifb->ifb_name, sizeof(ifb->ifb_name), "%s%d",
ifc->ifc_name, unit) >= sizeof(ifb->ifb_name)) {
ifbond_release(ifb);
return (EINVAL);
}
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;
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);
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;
}
-static void
+static int
bond_clone_destroy(struct ifnet * ifp)
{
ifbond_ref ifb;
ifb = ifnet_softc(ifp);
if (ifb == NULL || ifnet_type(ifp) != IFT_IEEE8023ADLAG) {
bond_unlock();
- return;
+ return 0;
}
if (ifbond_flags_if_detaching(ifb)) {
bond_unlock();
- return;
+ return 0;
}
bond_remove(ifb);
bond_unlock();
bond_if_detach(ifp);
- return;
+ return 0;
}
static int
}
static struct mbuf *
-S_mbuf_skip_to_offset(struct mbuf * m, long * offset)
+S_mbuf_skip_to_offset(struct mbuf * m, int32_t * offset)
{
int len;
#endif /* BYTE_ORDER == LITTLE_ENDIAN */
static int
-S_mbuf_copy_uint32(struct mbuf * m, long offset, uint32_t * val)
+S_mbuf_copy_uint32(struct mbuf * m, int32_t offset, uint32_t * val)
{
struct mbuf * current;
u_char * current_data;
struct in_addr ip_dst;
struct in_addr ip_src;
u_char ip_p;
- long offset;
+ int32_t offset;
struct mbuf * orig_m = m;
/* find the IP protocol field relative to the start of the packet */
{
u_char * data;
int i;
- long offset;
+ int32_t offset;
struct mbuf * orig_m = m;
uint32_t * scan;
uint32_t val;
uint32_t h;
ifbond_ref ifb;
struct ifnet * port_ifp = NULL;
+ int err;
+ struct flowadv adv = { FADV_SUCCESS };
if (m == 0) {
return (0);
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;
}
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();
}
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;
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_long)snprintf(p->po_name, sizeof(p->po_name), "%s%d",
+ if ((u_int32_t)snprintf(p->po_name, sizeof(p->po_name), "%s%d",
ifnet_name(port_ifp), ifnet_unit(port_ifp))
>= sizeof(p->po_name)) {
printf("if_bond: name too large\n");
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);
/* 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);
}
/* 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",
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;
}
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",
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;
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 0
return (error);
}
}
static int
-bond_ioctl(struct ifnet *ifp, u_int32_t cmd, void * data)
+bond_ioctl(struct ifnet *ifp, u_long cmd, void * data)
{
int error = 0;
struct if_bond_req ibr;
struct ifaddr * ifa;
ifbond_ref ifb;
struct ifreq * ifr;
- struct ifmediareq64 *ifmr;
+ struct ifmediareq *ifmr;
struct ifnet * port_ifp = NULL;
user_addr_t user_addr;
ifnet_set_flags(ifp, IFF_UP, IFF_UP);
break;
+ case SIOCGIFMEDIA32:
case SIOCGIFMEDIA64:
- case SIOCGIFMEDIA:
bond_lock();
ifb = (ifbond_ref)ifnet_softc(ifp);
if (ifb == NULL || ifbond_flags_if_detaching(ifb)) {
bond_unlock();
return (ifb == NULL ? EOPNOTSUPP : EBUSY);
}
- ifmr = (struct ifmediareq64 *)data;
+ ifmr = (struct ifmediareq *)data;
ifmr->ifm_current = IFM_ETHER;
ifmr->ifm_mask = 0;
ifmr->ifm_status = IFM_AVALID;
ifmr->ifm_status |= IFM_ACTIVE;
}
bond_unlock();
- user_addr = proc_is64bit(current_proc())
- ? ifmr->ifm_ifmu.ifmu_ulist64
- : CAST_USER_ADDR_T(ifmr->ifm_ifmu.ifmu_ulist32);
+ user_addr = (cmd == SIOCGIFMEDIA64) ?
+ ((struct ifmediareq64 *)ifmr)->ifmu_ulist :
+ CAST_USER_ADDR_T(((struct ifmediareq32 *)ifmr)->ifmu_ulist);
if (user_addr != USER_ADDR_NULL) {
error = copyout(&ifmr->ifm_current,
user_addr,
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;
}
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:
}
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:
}
static void
-interface_link_event(struct ifnet * ifp, u_long event_code)
+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)
{
struct {
struct kern_event_msg header;
- u_long unit;
+ u_int32_t unit;
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;
event.header.kev_subclass = KEV_DL_SUBCLASS;
event.header.event_code = event_code;
event.header.event_data[0] = ifnet_family(ifp);
- event.unit = (u_long) ifnet_unit(ifp);
- strncpy(event.if_name, ifnet_name(ifp), IFNAMSIZ);
+ event.unit = (u_int32_t) ifnet_unit(ifp);
+ strlcpy(event.if_name, ifnet_name(ifp), IFNAMSIZ);
ifnet_event(ifp, &event.header);
return;
}
bzero(®, sizeof(reg));
reg.input = bond_input;
reg.event = bond_event;
+ reg.detached = bond_detached;
error = ifnet_attach_protocol(ifp, PF_BOND, ®);
if (error) {
goto done;
}
#endif
- error = proto_register_plumber(PF_APPLETALK, APPLE_IF_FAM_BOND,
- ether_attach_at,
- ether_detach_at);
+ error = bond_clone_attach();
if (error != 0) {
- printf("bond: proto_register_plumber failed for AppleTalk error=%d\n",
- error);
- goto done;
+ printf("bond: proto_register_plumber failed bond_clone_attach error=%d\n",
+ error);
+ goto done;
}
- bond_clone_attach();
done:
return (error);
}
return;
}
-#endif 0
+#endif
static int
ifbond_all_ports_ready(ifbond_ref bond)
**/
static int
bondport_can_transmit(bondport_ref p, int32_t current_secs,
- long * next_secs)
+ __darwin_time_t * next_secs)
{
if (p->po_last_transmit_secs != current_secs) {
p->po_last_transmit_secs = current_secs;