/*
- * Copyright (c) 2004-2010 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2004-2012 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
};
/* 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);
}
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);
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));
}
TAILQ_INIT(&b->ifbond_list);
b->system = *sys;
b->system_priority = sys_pri;
-#if 0
- b->verbose = 1;
-#endif
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;
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;
}
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;
}
uint32_t h;
ifbond_ref ifb;
struct ifnet * port_ifp = NULL;
+ int err;
+ struct flowadv adv = { FADV_SUCCESS };
if (m == 0) {
return (0);
}
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();
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);
}
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:
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)
{
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;
bzero(®, sizeof(reg));
reg.input = bond_input;
reg.event = bond_event;
+ reg.detached = bond_detached;
error = ifnet_attach_protocol(ifp, PF_BOND, ®);
if (error) {