Date: Sat, 9 Mar 2013 01:39:43 +0000 (UTC) From: Attilio Rao <attilio@FreeBSD.org> To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r248080 - in user/attilio/vmobj-rwlock: . sbin/geom/class/raid sys/arm/arm sys/dev/drm2 sys/dev/drm2/ttm sys/dev/oce sys/geom/label sys/geom/raid sys/kern sys/modules/ath sys/net sys/ne... Message-ID: <201303090139.r291dhG7049757@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: attilio Date: Sat Mar 9 01:39:42 2013 New Revision: 248080 URL: http://svnweb.freebsd.org/changeset/base/248080 Log: MFC Modified: user/attilio/vmobj-rwlock/UPDATING user/attilio/vmobj-rwlock/sbin/geom/class/raid/graid.8 user/attilio/vmobj-rwlock/sys/arm/arm/cpufunc_asm_arm11x6.S user/attilio/vmobj-rwlock/sys/dev/drm2/drm_fb_helper.c user/attilio/vmobj-rwlock/sys/dev/drm2/drm_global.c user/attilio/vmobj-rwlock/sys/dev/drm2/ttm/ttm_bo.c user/attilio/vmobj-rwlock/sys/dev/drm2/ttm/ttm_memory.c user/attilio/vmobj-rwlock/sys/dev/oce/oce_hw.h user/attilio/vmobj-rwlock/sys/dev/oce/oce_sysctl.c user/attilio/vmobj-rwlock/sys/geom/label/g_label_ntfs.c user/attilio/vmobj-rwlock/sys/geom/raid/g_raid.c user/attilio/vmobj-rwlock/sys/kern/kern_timeout.c user/attilio/vmobj-rwlock/sys/kern/subr_param.c user/attilio/vmobj-rwlock/sys/modules/ath/Makefile user/attilio/vmobj-rwlock/sys/net/if.c user/attilio/vmobj-rwlock/sys/net/route.c user/attilio/vmobj-rwlock/sys/net/route.h user/attilio/vmobj-rwlock/sys/net80211/ieee80211.c user/attilio/vmobj-rwlock/sys/net80211/ieee80211_freebsd.c user/attilio/vmobj-rwlock/sys/net80211/ieee80211_freebsd.h user/attilio/vmobj-rwlock/sys/net80211/ieee80211_hostap.c user/attilio/vmobj-rwlock/sys/net80211/ieee80211_ht.c user/attilio/vmobj-rwlock/sys/net80211/ieee80211_hwmp.c user/attilio/vmobj-rwlock/sys/net80211/ieee80211_mesh.c user/attilio/vmobj-rwlock/sys/net80211/ieee80211_output.c user/attilio/vmobj-rwlock/sys/net80211/ieee80211_power.c user/attilio/vmobj-rwlock/sys/net80211/ieee80211_proto.h user/attilio/vmobj-rwlock/sys/net80211/ieee80211_superg.c user/attilio/vmobj-rwlock/sys/net80211/ieee80211_var.h user/attilio/vmobj-rwlock/sys/net80211/ieee80211_wds.c user/attilio/vmobj-rwlock/sys/sparc64/conf/GENERIC user/attilio/vmobj-rwlock/sys/sys/callout.h user/attilio/vmobj-rwlock/sys/sys/systm.h user/attilio/vmobj-rwlock/sys/vm/vm_init.c user/attilio/vmobj-rwlock/usr.sbin/pkg/pkg.c Directory Properties: user/attilio/vmobj-rwlock/ (props changed) user/attilio/vmobj-rwlock/sbin/ (props changed) user/attilio/vmobj-rwlock/sys/ (props changed) Modified: user/attilio/vmobj-rwlock/UPDATING ============================================================================== --- user/attilio/vmobj-rwlock/UPDATING Sat Mar 9 01:05:36 2013 (r248079) +++ user/attilio/vmobj-rwlock/UPDATING Sat Mar 9 01:39:42 2013 (r248080) @@ -26,6 +26,10 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 10 disable the most expensive debugging functionality run "ln -s 'abort:false,junk:false' /etc/malloc.conf".) +20130308: + CTL_DISABLE has also been added to the sparc64 GENERIC (for further + information, see the respective 20130304 entry). + 20130304: Recent commits to callout(9) changed the size of struct callout, so the KBI is probably heavily disturbed. Also, some functions Modified: user/attilio/vmobj-rwlock/sbin/geom/class/raid/graid.8 ============================================================================== --- user/attilio/vmobj-rwlock/sbin/geom/class/raid/graid.8 Sat Mar 9 01:05:36 2013 (r248079) +++ user/attilio/vmobj-rwlock/sbin/geom/class/raid/graid.8 Sat Mar 9 01:39:42 2013 (r248080) @@ -305,6 +305,9 @@ Write errors are always considered as di Time to wait for missing array components on startup. .It Va kern.geom.raid. Ns Ar X Ns Va .enable : No 1 Enable taste for specific metadata or transformation module. +.It Va kern.geom.raid.legacy_aliases : No 0 +Enable geom raid emulation of /dev/ar%d devices from ataraid(4) +This should aid the upgrade of systems from legacy to modern releases. .El .Sh EXIT STATUS Exit status is 0 on success, and non-zero if the command fails. Modified: user/attilio/vmobj-rwlock/sys/arm/arm/cpufunc_asm_arm11x6.S ============================================================================== --- user/attilio/vmobj-rwlock/sys/arm/arm/cpufunc_asm_arm11x6.S Sat Mar 9 01:05:36 2013 (r248079) +++ user/attilio/vmobj-rwlock/sys/arm/arm/cpufunc_asm_arm11x6.S Sat Mar 9 01:39:42 2013 (r248080) @@ -62,6 +62,8 @@ #include <machine/asm.h> __FBSDID("$FreeBSD$"); + .cpu arm1136js + #if 0 #define Invalidate_I_cache(Rtmp1, Rtmp2) \ mcr p15, 0, Rtmp1, c7, c5, 0 /* Invalidate Entire I cache */ Modified: user/attilio/vmobj-rwlock/sys/dev/drm2/drm_fb_helper.c ============================================================================== --- user/attilio/vmobj-rwlock/sys/dev/drm2/drm_fb_helper.c Sat Mar 9 01:05:36 2013 (r248079) +++ user/attilio/vmobj-rwlock/sys/dev/drm2/drm_fb_helper.c Sat Mar 9 01:39:42 2013 (r248080) @@ -555,8 +555,11 @@ static void drm_fb_helper_crtc_free(stru for (i = 0; i < helper->connector_count; i++) free(helper->connector_info[i], DRM_MEM_KMS); free(helper->connector_info, DRM_MEM_KMS); - for (i = 0; i < helper->crtc_count; i++) + for (i = 0; i < helper->crtc_count; i++) { free(helper->crtc_info[i].mode_set.connectors, DRM_MEM_KMS); + if (helper->crtc_info[i].mode_set.mode) + drm_mode_destroy(helper->dev, helper->crtc_info[i].mode_set.mode); + } free(helper->crtc_info, DRM_MEM_KMS); } Modified: user/attilio/vmobj-rwlock/sys/dev/drm2/drm_global.c ============================================================================== --- user/attilio/vmobj-rwlock/sys/dev/drm2/drm_global.c Sat Mar 9 01:05:36 2013 (r248079) +++ user/attilio/vmobj-rwlock/sys/dev/drm2/drm_global.c Sat Mar 9 01:39:42 2013 (r248080) @@ -104,6 +104,7 @@ void drm_global_item_unref(struct drm_gl MPASS(ref->object == item->object); if (--item->refcount == 0) { ref->release(ref); + free(item->object, M_DRM_GLOBAL); item->object = NULL; } sx_xunlock(&item->mutex); Modified: user/attilio/vmobj-rwlock/sys/dev/drm2/ttm/ttm_bo.c ============================================================================== --- user/attilio/vmobj-rwlock/sys/dev/drm2/ttm/ttm_bo.c Sat Mar 9 01:05:36 2013 (r248079) +++ user/attilio/vmobj-rwlock/sys/dev/drm2/ttm/ttm_bo.c Sat Mar 9 01:39:42 2013 (r248080) @@ -1400,7 +1400,6 @@ static void ttm_bo_global_kobj_release(s ttm_mem_unregister_shrink(glob->mem_glob, &glob->shrink); vm_page_free(glob->dummy_read_page); - free(glob, M_DRM_GLOBAL); } void ttm_bo_global_release(struct drm_global_reference *ref) Modified: user/attilio/vmobj-rwlock/sys/dev/drm2/ttm/ttm_memory.c ============================================================================== --- user/attilio/vmobj-rwlock/sys/dev/drm2/ttm/ttm_memory.c Sat Mar 9 01:05:36 2013 (r248079) +++ user/attilio/vmobj-rwlock/sys/dev/drm2/ttm/ttm_memory.c Sat Mar 9 01:39:42 2013 (r248080) @@ -125,8 +125,6 @@ static ssize_t ttm_mem_zone_store(struct static void ttm_mem_global_kobj_release(struct ttm_mem_global *glob) { - - free(glob, M_TTM_ZONE); } static bool ttm_zones_above_swap_target(struct ttm_mem_global *glob, Modified: user/attilio/vmobj-rwlock/sys/dev/oce/oce_hw.h ============================================================================== --- user/attilio/vmobj-rwlock/sys/dev/oce/oce_hw.h Sat Mar 9 01:05:36 2013 (r248079) +++ user/attilio/vmobj-rwlock/sys/dev/oce/oce_hw.h Sat Mar 9 01:39:42 2013 (r248080) @@ -38,8 +38,6 @@ /* $FreeBSD$ */ -/* $FreeBSD$ */ - #include <sys/types.h> #undef _BIG_ENDIAN /* TODO */ Modified: user/attilio/vmobj-rwlock/sys/dev/oce/oce_sysctl.c ============================================================================== --- user/attilio/vmobj-rwlock/sys/dev/oce/oce_sysctl.c Sat Mar 9 01:05:36 2013 (r248079) +++ user/attilio/vmobj-rwlock/sys/dev/oce/oce_sysctl.c Sat Mar 9 01:39:42 2013 (r248080) @@ -38,8 +38,6 @@ /* $FreeBSD$ */ -/* $FreeBSD$ */ - #include "oce_if.h" Modified: user/attilio/vmobj-rwlock/sys/geom/label/g_label_ntfs.c ============================================================================== --- user/attilio/vmobj-rwlock/sys/geom/label/g_label_ntfs.c Sat Mar 9 01:05:36 2013 (r248079) +++ user/attilio/vmobj-rwlock/sys/geom/label/g_label_ntfs.c Sat Mar 9 01:39:42 2013 (r248080) @@ -115,7 +115,7 @@ g_label_ntfs_taste(struct g_consumer *cp mftrecsz = (char)bf->bf_mftrecsz; recsize = (mftrecsz > 0) ? (mftrecsz * bf->bf_bps * bf->bf_spc) : (1 << -mftrecsz); - if (recsize % pp->sectorsize != 0) + if (recsize == 0 || recsize % pp->sectorsize != 0) goto done; voloff = bf->bf_mftcn * bf->bf_spc * bf->bf_bps + Modified: user/attilio/vmobj-rwlock/sys/geom/raid/g_raid.c ============================================================================== --- user/attilio/vmobj-rwlock/sys/geom/raid/g_raid.c Sat Mar 9 01:05:36 2013 (r248079) +++ user/attilio/vmobj-rwlock/sys/geom/raid/g_raid.c Sat Mar 9 01:39:42 2013 (r248080) @@ -92,6 +92,11 @@ TUNABLE_INT("kern.geom.raid.idle_thresho SYSCTL_UINT(_kern_geom_raid, OID_AUTO, idle_threshold, CTLFLAG_RW, &g_raid_idle_threshold, 1000000, "Time in microseconds to consider a volume idle."); +static u_int ar_legacy_aliases = 1; +SYSCTL_INT(_kern_geom_raid, OID_AUTO, legacy_aliases, CTLFLAG_RW, + &ar_legacy_aliases, 0, "Create aliases named as the legacy ataraid style."); +TUNABLE_INT("kern.geom_raid.legacy_aliases", &ar_legacy_aliases); + #define MSLEEP(rv, ident, mtx, priority, wmesg, timeout) do { \ G_RAID_DEBUG(4, "%s: Sleeping %p.", __func__, (ident)); \ @@ -1637,6 +1642,7 @@ g_raid_launch_provider(struct g_raid_vol struct g_raid_softc *sc; struct g_provider *pp; char name[G_RAID_MAX_VOLUMENAME]; + char announce_buf[80], buf1[32]; off_t off; sc = vol->v_softc; @@ -1650,6 +1656,22 @@ g_raid_launch_provider(struct g_raid_vol /* Otherwise use sequential volume number. */ snprintf(name, sizeof(name), "raid/r%d", vol->v_global_id); } + + /* + * Create a /dev/ar%d that the old ataraid(4) stack once + * created as an alias for /dev/raid/r%d if requested. + * This helps going from stable/7 ataraid devices to newer + * FreeBSD releases. sbruno 07 MAY 2013 + */ + + if (ar_legacy_aliases) { + snprintf(announce_buf, sizeof(announce_buf), + "kern.devalias.%s", name); + snprintf(buf1, sizeof(buf1), + "ar%d", vol->v_global_id); + setenv(announce_buf, buf1); + } + pp = g_new_providerf(sc->sc_geom, "%s", name); pp->private = vol; pp->mediasize = vol->v_mediasize; Modified: user/attilio/vmobj-rwlock/sys/kern/kern_timeout.c ============================================================================== --- user/attilio/vmobj-rwlock/sys/kern/kern_timeout.c Sat Mar 9 01:05:36 2013 (r248079) +++ user/attilio/vmobj-rwlock/sys/kern/kern_timeout.c Sat Mar 9 01:39:42 2013 (r248080) @@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$"); #include <sys/systm.h> #include <sys/bus.h> #include <sys/callout.h> +#include <sys/file.h> #include <sys/interrupt.h> #include <sys/kernel.h> #include <sys/ktr.h> @@ -101,6 +102,11 @@ SYSCTL_INT(_debug, OID_AUTO, to_avg_mpca 0, "Average number of MP direct callouts made per callout_process call. " "Units = 1/1000"); #endif + +static int ncallout; +SYSCTL_INT(_kern, OID_AUTO, ncallout, CTLFLAG_RDTUN, &ncallout, 0, + "Number of entries in callwheel and size of timeout() preallocation"); + /* * TODO: * allocate more timeout table slots when table overflows. @@ -181,6 +187,7 @@ struct callout_cpu cc_cpu; static int timeout_cpu; +static void callout_cpu_init(struct callout_cpu *cc); static void softclock_call_cc(struct callout *c, struct callout_cpu *cc, #ifdef CALLOUT_PROFILING int *mpcalls, int *lockcalls, int *gcalls, @@ -240,18 +247,21 @@ cc_cce_migrating(struct callout_cpu *cc, } /* - * kern_timeout_callwheel_alloc() - kernel low level callwheel initialization - * - * This code is called very early in the kernel initialization sequence, - * and may be called more then once. + * Kernel low level callwheel initialization + * called on cpu0 during kernel startup. */ -caddr_t -kern_timeout_callwheel_alloc(caddr_t v) +static void +callout_callwheel_init(void *dummy) { struct callout_cpu *cc; - timeout_cpu = PCPU_GET(cpuid); - cc = CC_CPU(timeout_cpu); + /* + * Calculate the size of the callout wheel and the preallocated + * timeout() structures. + */ + ncallout = imin(16 + maxproc + maxfiles, 18508); + TUNABLE_INT_FETCH("kern.ncallout", &ncallout); + /* * Calculate callout wheel size, should be next power of two higher * than 'ncallout'. @@ -259,13 +269,23 @@ kern_timeout_callwheel_alloc(caddr_t v) callwheelsize = 1 << fls(ncallout); callwheelmask = callwheelsize - 1; - cc->cc_callout = (struct callout *)v; - v = (caddr_t)(cc->cc_callout + ncallout); - cc->cc_callwheel = (struct callout_list *)v; - v = (caddr_t)(cc->cc_callwheel + callwheelsize); - return(v); + /* + * Only cpu0 handles timeout(9) and receives a preallocation. + * + * XXX: Once all timeout(9) consumers are converted this can + * be removed. + */ + timeout_cpu = PCPU_GET(cpuid); + cc = CC_CPU(timeout_cpu); + cc->cc_callout = malloc(ncallout * sizeof(struct callout), + M_CALLOUT, M_WAITOK); + callout_cpu_init(cc); } +SYSINIT(callwheel_init, SI_SUB_CPU, SI_ORDER_ANY, callout_callwheel_init, NULL); +/* + * Initialize the per-cpu callout structures. + */ static void callout_cpu_init(struct callout_cpu *cc) { @@ -274,13 +294,15 @@ callout_cpu_init(struct callout_cpu *cc) mtx_init(&cc->cc_lock, "callout", NULL, MTX_SPIN | MTX_RECURSE); SLIST_INIT(&cc->cc_callfree); + cc->cc_callwheel = malloc(sizeof(struct callout_tailq) * callwheelsize, + M_CALLOUT, M_WAITOK); for (i = 0; i < callwheelsize; i++) LIST_INIT(&cc->cc_callwheel[i]); TAILQ_INIT(&cc->cc_expireq); cc->cc_firstevent = INT64_MAX; for (i = 0; i < 2; i++) cc_cce_cleanup(cc, i); - if (cc->cc_callout == NULL) + if (cc->cc_callout == NULL) /* Only cpu0 handles timeout(9) */ return; for (i = 0; i < ncallout; i++) { c = &cc->cc_callout[i]; @@ -321,19 +343,6 @@ callout_cpu_switch(struct callout *c, st #endif /* - * kern_timeout_callwheel_init() - initialize previously reserved callwheel - * space. - * - * This code is called just once, after the space reserved for the - * callout wheel has been finalized. - */ -void -kern_timeout_callwheel_init(void) -{ - callout_cpu_init(CC_CPU(timeout_cpu)); -} - -/* * Start standard softclock thread. */ static void @@ -353,18 +362,14 @@ start_softclock(void *dummy) if (cpu == timeout_cpu) continue; cc = CC_CPU(cpu); + cc->cc_callout = NULL; /* Only cpu0 handles timeout(9). */ + callout_cpu_init(cc); if (swi_add(NULL, "clock", softclock, cc, SWI_CLOCK, INTR_MPSAFE, &cc->cc_cookie)) panic("died while creating standard software ithreads"); - cc->cc_callout = NULL; /* Only cpu0 handles timeout(). */ - cc->cc_callwheel = malloc( - sizeof(struct callout_list) * callwheelsize, M_CALLOUT, - M_WAITOK); - callout_cpu_init(cc); } #endif } - SYSINIT(start_softclock, SI_SUB_SOFTINTR, SI_ORDER_FIRST, start_softclock, NULL); #define CC_HASH_SHIFT 8 Modified: user/attilio/vmobj-rwlock/sys/kern/subr_param.c ============================================================================== --- user/attilio/vmobj-rwlock/sys/kern/subr_param.c Sat Mar 9 01:05:36 2013 (r248079) +++ user/attilio/vmobj-rwlock/sys/kern/subr_param.c Sat Mar 9 01:39:42 2013 (r248080) @@ -91,7 +91,6 @@ int maxprocperuid; /* max # of procs p int maxfiles; /* sys. wide open files limit */ int maxfilesperproc; /* per-proc open files limit */ int msgbufsize; /* size of kernel message buffer */ -int ncallout; /* maximum # of timer events */ int nbuf; int ngroups_max; /* max # groups per process */ int nswbuf; @@ -109,8 +108,6 @@ u_long sgrowsiz; /* amount to grow sta SYSCTL_INT(_kern, OID_AUTO, hz, CTLFLAG_RDTUN, &hz, 0, "Number of clock ticks per second"); -SYSCTL_INT(_kern, OID_AUTO, ncallout, CTLFLAG_RDTUN, &ncallout, 0, - "Number of pre-allocated timer events"); SYSCTL_INT(_kern, OID_AUTO, nbuf, CTLFLAG_RDTUN, &nbuf, 0, "Number of buffers in the buffer cache"); SYSCTL_INT(_kern, OID_AUTO, nswbuf, CTLFLAG_RDTUN, &nswbuf, 0, @@ -327,15 +324,6 @@ init_param2(long physpages) TUNABLE_INT_FETCH("kern.nbuf", &nbuf); /* - * XXX: Does the callout wheel have to be so big? - * - * Clip callout to result of previous function of maxusers maximum - * 384. This is still huge, but acceptable. - */ - ncallout = imin(16 + maxproc + maxfiles, 18508); - TUNABLE_INT_FETCH("kern.ncallout", &ncallout); - - /* * The default for maxpipekva is min(1/64 of the kernel address space, * max(1/64 of main memory, 512KB)). See sys_pipe.c for more details. */ Modified: user/attilio/vmobj-rwlock/sys/modules/ath/Makefile ============================================================================== --- user/attilio/vmobj-rwlock/sys/modules/ath/Makefile Sat Mar 9 01:05:36 2013 (r248079) +++ user/attilio/vmobj-rwlock/sys/modules/ath/Makefile Sat Mar 9 01:39:42 2013 (r248080) @@ -123,6 +123,15 @@ SRCS+= ah_eeprom_9287.c .PATH: ${.CURDIR}/../../dev/ath/ath_hal/ar9002 SRCS+= ar9287.c ar9287_reset.c ar9287_attach.c ar9287_cal.c ar9287_olc.c +# + AR9300 HAL +# .PATH: ${.CURDIR}/../../dev/ath/ath_hal/ar9003 +#SRCS+= ar9300_interrupts.c ar9300_radar.c ar9300_ani.c ar9300_keycache.c +#SRCS+= ar9300_radio.c ar9300_xmit.c ar9300_attach.c ar9300_mci.c ar9300_stub.c +#SRCS+= ar9300_xmit_ds.c ar9300_beacon.c ar9300_misc.c ar9300_recv.c +#SRCS+= ar9300_stub_funcs.c ar9300_eeprom.c ar9300_paprd.c ar9300_recv_ds.c +#SRCS+= ar9300_freebsd.c ar9300_phy.c ar9300_reset.c ar9300_gpio.c +#SRCS+= ar9300_power.c ar9300_timer.c + # NB: rate control is bound to the driver by symbol names so only pick one .if ${ATH_RATE} == "sample" .PATH: ${.CURDIR}/../../dev/ath/ath_rate/sample Modified: user/attilio/vmobj-rwlock/sys/net/if.c ============================================================================== --- user/attilio/vmobj-rwlock/sys/net/if.c Sat Mar 9 01:05:36 2013 (r248079) +++ user/attilio/vmobj-rwlock/sys/net/if.c Sat Mar 9 01:39:42 2013 (r248080) @@ -1357,7 +1357,8 @@ if_rtdel(struct radix_node *rn, void *ar return (0); err = rtrequest_fib(RTM_DELETE, rt_key(rt), rt->rt_gateway, - rt_mask(rt), rt->rt_flags|RTF_RNH_LOCKED, + rt_mask(rt), + rt->rt_flags|RTF_RNH_LOCKED|RTF_PINNED, (struct rtentry **) NULL, rt->rt_fibnum); if (err) { log(LOG_WARNING, "if_rtdel: error %d\n", err); Modified: user/attilio/vmobj-rwlock/sys/net/route.c ============================================================================== --- user/attilio/vmobj-rwlock/sys/net/route.c Sat Mar 9 01:05:36 2013 (r248079) +++ user/attilio/vmobj-rwlock/sys/net/route.c Sat Mar 9 01:39:42 2013 (r248080) @@ -1112,6 +1112,14 @@ rtrequest1_fib(int req, struct rt_addrin error = 0; } #endif + if ((flags & RTF_PINNED) == 0) { + /* Check if target route can be deleted */ + rt = (struct rtentry *)rnh->rnh_lookup(dst, + netmask, rnh); + if ((rt != NULL) && (rt->rt_flags & RTF_PINNED)) + senderr(EADDRINUSE); + } + /* * Remove the item from the tree and return it. * Complain if it is not there and do no more processing. @@ -1430,6 +1438,7 @@ rtinit1(struct ifaddr *ifa, int cmd, int int didwork = 0; int a_failure = 0; static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK}; + struct radix_node_head *rnh; if (flags & RTF_HOST) { dst = ifa->ifa_dstaddr; @@ -1488,7 +1497,6 @@ rtinit1(struct ifaddr *ifa, int cmd, int */ for ( fibnum = startfib; fibnum <= endfib; fibnum++) { if (cmd == RTM_DELETE) { - struct radix_node_head *rnh; struct radix_node *rn; /* * Look up an rtentry that is in the routing tree and @@ -1538,7 +1546,8 @@ rtinit1(struct ifaddr *ifa, int cmd, int */ bzero((caddr_t)&info, sizeof(info)); info.rti_ifa = ifa; - info.rti_flags = flags | (ifa->ifa_flags & ~IFA_RTSELF); + info.rti_flags = flags | + (ifa->ifa_flags & ~IFA_RTSELF) | RTF_PINNED; info.rti_info[RTAX_DST] = dst; /* * doing this for compatibility reasons @@ -1550,6 +1559,33 @@ rtinit1(struct ifaddr *ifa, int cmd, int info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr; info.rti_info[RTAX_NETMASK] = netmask; error = rtrequest1_fib(cmd, &info, &rt, fibnum); + + if ((error == EEXIST) && (cmd == RTM_ADD)) { + /* + * Interface route addition failed. + * Atomically delete current prefix generating + * RTM_DELETE message, and retry adding + * interface prefix. + */ + rnh = rt_tables_get_rnh(fibnum, dst->sa_family); + RADIX_NODE_HEAD_LOCK(rnh); + + /* Delete old prefix */ + info.rti_ifa = NULL; + info.rti_flags = RTF_RNH_LOCKED; + + error = rtrequest1_fib(RTM_DELETE, &info, &rt, fibnum); + if (error == 0) { + info.rti_ifa = ifa; + info.rti_flags = flags | RTF_RNH_LOCKED | + (ifa->ifa_flags & ~IFA_RTSELF) | RTF_PINNED; + error = rtrequest1_fib(cmd, &info, &rt, fibnum); + } + + RADIX_NODE_HEAD_UNLOCK(rnh); + } + + if (error == 0 && rt != NULL) { /* * notify any listening routing agents of the change Modified: user/attilio/vmobj-rwlock/sys/net/route.h ============================================================================== --- user/attilio/vmobj-rwlock/sys/net/route.h Sat Mar 9 01:05:36 2013 (r248079) +++ user/attilio/vmobj-rwlock/sys/net/route.h Sat Mar 9 01:39:42 2013 (r248080) @@ -176,7 +176,7 @@ struct ortentry { /* 0x20000 unused, was RTF_WASCLONED */ #define RTF_PROTO3 0x40000 /* protocol specific routing flag */ /* 0x80000 unused */ -#define RTF_PINNED 0x100000 /* future use */ +#define RTF_PINNED 0x100000 /* route is immutable */ #define RTF_LOCAL 0x200000 /* route represents a local address */ #define RTF_BROADCAST 0x400000 /* route represents a bcast address */ #define RTF_MULTICAST 0x800000 /* route represents a mcast address */ Modified: user/attilio/vmobj-rwlock/sys/net80211/ieee80211.c ============================================================================== --- user/attilio/vmobj-rwlock/sys/net80211/ieee80211.c Sat Mar 9 01:05:36 2013 (r248079) +++ user/attilio/vmobj-rwlock/sys/net80211/ieee80211.c Sat Mar 9 01:39:42 2013 (r248080) @@ -278,6 +278,7 @@ ieee80211_ifattach(struct ieee80211com * KASSERT(ifp->if_type == IFT_IEEE80211, ("if_type %d", ifp->if_type)); IEEE80211_LOCK_INIT(ic, ifp->if_xname); + IEEE80211_TX_LOCK_INIT(ic, ifp->if_xname); TAILQ_INIT(&ic->ic_vaps); /* Create a taskqueue for all state changes */ @@ -385,6 +386,7 @@ ieee80211_ifdetach(struct ieee80211com * ifmedia_removeall(&ic->ic_media); taskqueue_free(ic->ic_tq); + IEEE80211_TX_LOCK_DESTROY(ic); IEEE80211_LOCK_DESTROY(ic); } Modified: user/attilio/vmobj-rwlock/sys/net80211/ieee80211_freebsd.c ============================================================================== --- user/attilio/vmobj-rwlock/sys/net80211/ieee80211_freebsd.c Sat Mar 9 01:05:36 2013 (r248079) +++ user/attilio/vmobj-rwlock/sys/net80211/ieee80211_freebsd.c Sat Mar 9 01:39:42 2013 (r248080) @@ -504,6 +504,44 @@ ieee80211_process_callback(struct ieee80 } } +/* + * Transmit a frame to the parent interface. + * + * TODO: if the transmission fails, make sure the parent node is freed + * (the callers will first need modifying.) + */ +int +ieee80211_parent_transmit(struct ieee80211com *ic, + struct mbuf *m) +{ + struct ifnet *parent = ic->ic_ifp; + /* + * Assert the IC TX lock is held - this enforces the + * processing -> queuing order is maintained + */ + IEEE80211_TX_LOCK_ASSERT(ic); + + return (parent->if_transmit(parent, m)); +} + +/* + * Transmit a frame to the VAP interface. + */ +int +ieee80211_vap_transmit(struct ieee80211vap *vap, struct mbuf *m) +{ + struct ifnet *ifp = vap->iv_ifp; + + /* + * When transmitting via the VAP, we shouldn't hold + * any IC TX lock as the VAP TX path will acquire it. + */ + IEEE80211_TX_UNLOCK_ASSERT(vap->iv_ic); + + return (ifp->if_transmit(ifp, m)); + +} + #include <sys/libkern.h> void Modified: user/attilio/vmobj-rwlock/sys/net80211/ieee80211_freebsd.h ============================================================================== --- user/attilio/vmobj-rwlock/sys/net80211/ieee80211_freebsd.h Sat Mar 9 01:05:36 2013 (r248079) +++ user/attilio/vmobj-rwlock/sys/net80211/ieee80211_freebsd.h Sat Mar 9 01:39:42 2013 (r248080) @@ -57,6 +57,30 @@ typedef struct { mtx_assert(IEEE80211_LOCK_OBJ(_ic), MA_NOTOWNED) /* + * Transmit lock. + * + * This is a (mostly) temporary lock designed to serialise all of the + * transmission operations throughout the stack. + */ +typedef struct { + char name[16]; /* e.g. "ath0_com_lock" */ + struct mtx mtx; +} ieee80211_tx_lock_t; +#define IEEE80211_TX_LOCK_INIT(_ic, _name) do { \ + ieee80211_tx_lock_t *cl = &(_ic)->ic_txlock; \ + snprintf(cl->name, sizeof(cl->name), "%s_tx_lock", _name); \ + mtx_init(&cl->mtx, cl->name, NULL, MTX_DEF); \ +} while (0) +#define IEEE80211_TX_LOCK_OBJ(_ic) (&(_ic)->ic_txlock.mtx) +#define IEEE80211_TX_LOCK_DESTROY(_ic) mtx_destroy(IEEE80211_TX_LOCK_OBJ(_ic)) +#define IEEE80211_TX_LOCK(_ic) mtx_lock(IEEE80211_TX_LOCK_OBJ(_ic)) +#define IEEE80211_TX_UNLOCK(_ic) mtx_unlock(IEEE80211_TX_LOCK_OBJ(_ic)) +#define IEEE80211_TX_LOCK_ASSERT(_ic) \ + mtx_assert(IEEE80211_TX_LOCK_OBJ(_ic), MA_OWNED) +#define IEEE80211_TX_UNLOCK_ASSERT(_ic) \ + mtx_assert(IEEE80211_TX_LOCK_OBJ(_ic), MA_NOTOWNED) + +/* * Node locking definitions. */ typedef struct { @@ -272,9 +296,11 @@ int ieee80211_add_callback(struct mbuf * void (*func)(struct ieee80211_node *, void *, int), void *arg); void ieee80211_process_callback(struct ieee80211_node *, struct mbuf *, int); -void get_random_bytes(void *, size_t); - struct ieee80211com; +int ieee80211_parent_transmit(struct ieee80211com *, struct mbuf *); +int ieee80211_vap_transmit(struct ieee80211vap *, struct mbuf *); + +void get_random_bytes(void *, size_t); void ieee80211_sysctl_attach(struct ieee80211com *); void ieee80211_sysctl_detach(struct ieee80211com *); Modified: user/attilio/vmobj-rwlock/sys/net80211/ieee80211_hostap.c ============================================================================== --- user/attilio/vmobj-rwlock/sys/net80211/ieee80211_hostap.c Sat Mar 9 01:05:36 2013 (r248079) +++ user/attilio/vmobj-rwlock/sys/net80211/ieee80211_hostap.c Sat Mar 9 01:39:42 2013 (r248080) @@ -412,7 +412,7 @@ hostap_deliver_data(struct ieee80211vap if (mcopy != NULL) { int len, err; len = mcopy->m_pkthdr.len; - err = ifp->if_transmit(ifp, mcopy); + err = ieee80211_vap_transmit(vap, mcopy); if (err) { /* NB: IFQ_HANDOFF reclaims mcopy */ } else { @@ -2255,8 +2255,8 @@ void ieee80211_recv_pspoll(struct ieee80211_node *ni, struct mbuf *m0) { struct ieee80211vap *vap = ni->ni_vap; + struct ieee80211com *ic = vap->iv_ic; struct ieee80211_frame_min *wh; - struct ifnet *ifp; struct mbuf *m; uint16_t aid; int qlen; @@ -2320,23 +2320,15 @@ ieee80211_recv_pspoll(struct ieee80211_n } m->m_flags |= M_PWR_SAV; /* bypass PS handling */ - if (m->m_flags & M_ENCAP) - ifp = vap->iv_ic->ic_ifp; - else - ifp = vap->iv_ifp; - /* - * Free any node ref which this mbuf may have. - * - * Much like psq_mfree(), we assume that M_ENCAP nodes have - * node references. + * Do the right thing; if it's an encap'ed frame then + * call ieee80211_parent_transmit() (and free the ref) else + * call ieee80211_vap_transmit(). */ - if (ifp->if_transmit(ifp, m) != 0) { - /* - * XXX m is invalid (freed) at this point, determine M_ENCAP - * an alternate way. - */ - if (ifp == vap->iv_ic->ic_ifp) + if (m->m_flags & M_ENCAP) { + if (ieee80211_parent_transmit(ic, m) != 0) ieee80211_free_node(ni); + } else { + (void) ieee80211_vap_transmit(vap, m); } } Modified: user/attilio/vmobj-rwlock/sys/net80211/ieee80211_ht.c ============================================================================== --- user/attilio/vmobj-rwlock/sys/net80211/ieee80211_ht.c Sat Mar 9 01:05:36 2013 (r248079) +++ user/attilio/vmobj-rwlock/sys/net80211/ieee80211_ht.c Sat Mar 9 01:39:42 2013 (r248080) @@ -2392,7 +2392,9 @@ ieee80211_send_bar(struct ieee80211_node * ic_raw_xmit will free the node reference * regardless of queue/TX success or failure. */ - ret = ic->ic_raw_xmit(ni, m, NULL); + IEEE80211_TX_LOCK(ic); + ret = ieee80211_raw_output(vap, ni, m, NULL); + IEEE80211_TX_UNLOCK(ic); if (ret != 0) { IEEE80211_NOTE(vap, IEEE80211_MSG_DEBUG | IEEE80211_MSG_11N, ni, "send BAR: failed: (ret = %d)\n", Modified: user/attilio/vmobj-rwlock/sys/net80211/ieee80211_hwmp.c ============================================================================== --- user/attilio/vmobj-rwlock/sys/net80211/ieee80211_hwmp.c Sat Mar 9 01:05:36 2013 (r248079) +++ user/attilio/vmobj-rwlock/sys/net80211/ieee80211_hwmp.c Sat Mar 9 01:39:42 2013 (r248080) @@ -592,6 +592,7 @@ hwmp_send_action(struct ieee80211vap *va struct ieee80211_bpf_params params; struct mbuf *m; uint8_t *frm; + int ret; if (IEEE80211_IS_MULTICAST(da)) { ni = ieee80211_ref_node(vap->iv_bss); @@ -654,6 +655,9 @@ hwmp_send_action(struct ieee80211vap *va vap->iv_stats.is_tx_nobuf++; return ENOMEM; } + + IEEE80211_TX_LOCK(ic); + ieee80211_send_setup(ni, m, IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_ACTION, IEEE80211_NONQOS_TID, vap->iv_myaddr, da, vap->iv_myaddr); @@ -669,7 +673,9 @@ hwmp_send_action(struct ieee80211vap *va else params.ibp_try0 = ni->ni_txparms->maxretry; params.ibp_power = ni->ni_txpower; - return ic->ic_raw_xmit(ni, m, ¶ms); + ret = ieee80211_raw_output(vap, ni, m, ¶ms); + IEEE80211_TX_UNLOCK(ic); + return (ret); } #define ADDSHORT(frm, v) do { \ @@ -1271,12 +1277,9 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_mesh_route *rtext = NULL; struct ieee80211_hwmp_route *hr; struct ieee80211com *ic = vap->iv_ic; - struct ifnet *ifp = vap->iv_ifp; struct mbuf *m, *next; uint32_t metric = 0; const uint8_t *addr; - int is_encap; - struct ieee80211_node *ni_encap; IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, "received PREP, orig %6D, targ %6D", prep->prep_origaddr, ":", @@ -1450,22 +1453,21 @@ hwmp_recv_prep(struct ieee80211vap *vap, m = ieee80211_ageq_remove(&ic->ic_stageq, (struct ieee80211_node *)(uintptr_t) ieee80211_mac_hash(ic, addr)); /* either dest or ext_dest */ + + /* + * All frames in the stageq here should be non-M_ENCAP; or things + * will get very unhappy. + */ for (; m != NULL; m = next) { - is_encap = !! (m->m_flags & M_ENCAP); - ni_encap = (struct ieee80211_node *) m->m_pkthdr.rcvif; next = m->m_nextpkt; m->m_nextpkt = NULL; IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, "flush queued frame %p len %d", m, m->m_pkthdr.len); - /* * If the mbuf has M_ENCAP set, ensure we free it. * Note that after if_transmit() is called, m is invalid. */ - if (ifp->if_transmit(ifp, m) != 0) { - if (is_encap) - ieee80211_free_node(ni_encap); - } + (void) ieee80211_vap_transmit(vap, m); } #undef IS_PROXY #undef PROXIED_BY_US Modified: user/attilio/vmobj-rwlock/sys/net80211/ieee80211_mesh.c ============================================================================== --- user/attilio/vmobj-rwlock/sys/net80211/ieee80211_mesh.c Sat Mar 9 01:05:36 2013 (r248079) +++ user/attilio/vmobj-rwlock/sys/net80211/ieee80211_mesh.c Sat Mar 9 01:39:42 2013 (r248080) @@ -1041,11 +1041,12 @@ mesh_transmit_to_gate(struct ieee80211va { struct ifnet *ifp = vap->iv_ifp; struct ieee80211com *ic = vap->iv_ic; - struct ifnet *parent = ic->ic_ifp; struct ieee80211_node *ni; struct ether_header *eh; int error; + IEEE80211_TX_UNLOCK_ASSERT(ic); + eh = mtod(m, struct ether_header *); ni = ieee80211_mesh_find_txnode(vap, rt_gate->rt_dest); if (ni == NULL) { @@ -1132,6 +1133,8 @@ mesh_transmit_to_gate(struct ieee80211va } } #endif /* IEEE80211_SUPPORT_SUPERG */ + + IEEE80211_TX_LOCK(ic); if (__predict_true((vap->iv_caps & IEEE80211_C_8023ENCAP) == 0)) { /* * Encapsulate the packet in prep for transmission. @@ -1143,9 +1146,9 @@ mesh_transmit_to_gate(struct ieee80211va return; } } - error = parent->if_transmit(parent, m); + error = ieee80211_parent_transmit(ic, m); + IEEE80211_TX_UNLOCK(ic); if (error != 0) { - m_freem(m); ieee80211_free_node(ni); } else { ifp->if_opackets++; @@ -1171,6 +1174,8 @@ ieee80211_mesh_forward_to_gates(struct i struct ieee80211_mesh_gate_route *gr = NULL, *gr_next; struct mbuf *m, *mcopy, *next; + IEEE80211_TX_UNLOCK_ASSERT(ic); + KASSERT( rt_dest->rt_flags == IEEE80211_MESHRT_FLAGS_DISCOVER, ("Route is not marked with IEEE80211_MESHRT_FLAGS_DISCOVER")); @@ -1240,7 +1245,6 @@ mesh_forward(struct ieee80211vap *vap, s struct ieee80211com *ic = vap->iv_ic; struct ieee80211_mesh_state *ms = vap->iv_mesh; struct ifnet *ifp = vap->iv_ifp; - struct ifnet *parent = ic->ic_ifp; const struct ieee80211_frame *wh = mtod(m, const struct ieee80211_frame *); struct mbuf *mcopy; @@ -1249,6 +1253,9 @@ mesh_forward(struct ieee80211vap *vap, s struct ieee80211_node *ni; int err; + /* This is called from the RX path - don't hold this lock */ + IEEE80211_TX_UNLOCK_ASSERT(ic); + /* * mesh ttl of 1 means we are the last one receving it, * according to amendment we decrement and then check if @@ -1320,7 +1327,20 @@ mesh_forward(struct ieee80211vap *vap, s /* XXX do we know m_nextpkt is NULL? */ mcopy->m_pkthdr.rcvif = (void *) ni; - err = parent->if_transmit(parent, mcopy); + + /* + * XXX this bypasses all of the VAP TX handling; it passes frames + * directly to the parent interface. + * + * Because of this, there's no TX lock being held as there's no + * encaps state being used. + * + * Doing a direct parent transmit may not be the correct thing + * to do here; we'll have to re-think this soon. + */ + IEEE80211_TX_LOCK(ic); + err = ieee80211_parent_transmit(ic, mcopy); + IEEE80211_TX_UNLOCK(ic); if (err != 0) { /* NB: IFQ_HANDOFF reclaims mbuf */ ieee80211_free_node(ni); @@ -1457,6 +1477,10 @@ mesh_recv_indiv_data_to_fwrd(struct ieee struct ieee80211_qosframe_addr4 *qwh; struct ieee80211_mesh_state *ms = vap->iv_mesh; struct ieee80211_mesh_route *rt_meshda, *rt_meshsa; + struct ieee80211com *ic = vap->iv_ic; + + /* This is called from the RX path - don't hold this lock */ + IEEE80211_TX_UNLOCK_ASSERT(ic); qwh = (struct ieee80211_qosframe_addr4 *)wh; @@ -1512,8 +1536,12 @@ mesh_recv_indiv_data_to_me(struct ieee80 const struct ieee80211_meshcntl_ae10 *mc10; struct ieee80211_mesh_state *ms = vap->iv_mesh; struct ieee80211_mesh_route *rt; + struct ieee80211com *ic = vap->iv_ic; int ae; + /* This is called from the RX path - don't hold this lock */ + IEEE80211_TX_UNLOCK_ASSERT(ic); + qwh = (struct ieee80211_qosframe_addr4 *)wh; mc10 = (const struct ieee80211_meshcntl_ae10 *)mc; @@ -1575,6 +1603,10 @@ mesh_recv_group_data(struct ieee80211vap { #define MC01(mc) ((const struct ieee80211_meshcntl_ae01 *)mc) struct ieee80211_mesh_state *ms = vap->iv_mesh; + struct ieee80211com *ic = vap->iv_ic; + + /* This is called from the RX path - don't hold this lock */ + IEEE80211_TX_UNLOCK_ASSERT(ic); mesh_forward(vap, m, mc); @@ -1621,6 +1653,9 @@ mesh_input(struct ieee80211_node *ni, st need_tap = 1; /* mbuf need to be tapped. */ type = -1; /* undefined */ + /* This is called from the RX path - don't hold this lock */ + IEEE80211_TX_UNLOCK_ASSERT(ic); + if (m->m_pkthdr.len < sizeof(struct ieee80211_frame_min)) { IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY, ni->ni_macaddr, NULL, @@ -2743,6 +2778,7 @@ mesh_send_action(struct ieee80211_node * struct ieee80211com *ic = ni->ni_ic; struct ieee80211_bpf_params params; struct ieee80211_frame *wh; + int ret; KASSERT(ni != NULL, ("null node")); @@ -2761,6 +2797,7 @@ mesh_send_action(struct ieee80211_node * return ENOMEM; } + IEEE80211_TX_LOCK(ic); wh = mtod(m, struct ieee80211_frame *); ieee80211_send_setup(ni, m, IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_ACTION, @@ -2778,7 +2815,9 @@ mesh_send_action(struct ieee80211_node * IEEE80211_NODE_STAT(ni, tx_mgmt); - return ic->ic_raw_xmit(ni, m, ¶ms); + ret = ieee80211_raw_output(vap, ni, m, ¶ms); + IEEE80211_TX_UNLOCK(ic); + return (ret); } #define ADDSHORT(frm, v) do { \ Modified: user/attilio/vmobj-rwlock/sys/net80211/ieee80211_output.c ============================================================================== --- user/attilio/vmobj-rwlock/sys/net80211/ieee80211_output.c Sat Mar 9 01:05:36 2013 (r248079) +++ user/attilio/vmobj-rwlock/sys/net80211/ieee80211_output.c Sat Mar 9 01:39:42 2013 (r248080) @@ -110,6 +110,255 @@ doprint(struct ieee80211vap *vap, int su #endif /* + * Send the given mbuf through the given vap. + * + * This consumes the mbuf regardless of whether the transmit + * was successful or not. + * + * This does none of the initial checks that ieee80211_start() + * does (eg CAC timeout, interface wakeup) - the caller must + * do this first. + */ +static int +ieee80211_start_pkt(struct ieee80211vap *vap, struct mbuf *m) +{ +#define IS_DWDS(vap) \ + (vap->iv_opmode == IEEE80211_M_WDS && \ + (vap->iv_flags_ext & IEEE80211_FEXT_WDSLEGACY) == 0) + struct ieee80211com *ic = vap->iv_ic; + struct ifnet *ifp = vap->iv_ifp; + struct ieee80211_node *ni; + struct ether_header *eh; + int error; + + /* + * Cancel any background scan. + */ + if (ic->ic_flags & IEEE80211_F_SCAN) + ieee80211_cancel_anyscan(vap); + /* + * Find the node for the destination so we can do + * things like power save and fast frames aggregation. + * + * NB: past this point various code assumes the first + * mbuf has the 802.3 header present (and contiguous). + */ + ni = NULL; + if (m->m_len < sizeof(struct ether_header) && + (m = m_pullup(m, sizeof(struct ether_header))) == NULL) { + IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT, + "discard frame, %s\n", "m_pullup failed"); + vap->iv_stats.is_tx_nobuf++; /* XXX */ + ifp->if_oerrors++; + return (ENOBUFS); + } + eh = mtod(m, struct ether_header *); + if (ETHER_IS_MULTICAST(eh->ether_dhost)) { + if (IS_DWDS(vap)) { + /* + * Only unicast frames from the above go out + * DWDS vaps; multicast frames are handled by + * dispatching the frame as it comes through + * the AP vap (see below). + */ + IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_WDS, + eh->ether_dhost, "mcast", "%s", "on DWDS"); + vap->iv_stats.is_dwds_mcast++; + m_freem(m); + /* XXX better status? */ + return (ENOBUFS); + } + if (vap->iv_opmode == IEEE80211_M_HOSTAP) { + /* + * Spam DWDS vap's w/ multicast traffic. + */ + /* XXX only if dwds in use? */ + ieee80211_dwds_mcast(vap, m); + } + } +#ifdef IEEE80211_SUPPORT_MESH + if (vap->iv_opmode != IEEE80211_M_MBSS) { +#endif + ni = ieee80211_find_txnode(vap, eh->ether_dhost); + if (ni == NULL) { + /* NB: ieee80211_find_txnode does stat+msg */ + ifp->if_oerrors++; + m_freem(m); + /* XXX better status? */ + return (ENOBUFS); + } + if (ni->ni_associd == 0 && + (ni->ni_flags & IEEE80211_NODE_ASSOCID)) { + IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_OUTPUT, + eh->ether_dhost, NULL, + "sta not associated (type 0x%04x)", + htons(eh->ether_type)); + vap->iv_stats.is_tx_notassoc++; + ifp->if_oerrors++; + m_freem(m); + ieee80211_free_node(ni); + /* XXX better status? */ + return (ENOBUFS); + } +#ifdef IEEE80211_SUPPORT_MESH + } else { + if (!IEEE80211_ADDR_EQ(eh->ether_shost, vap->iv_myaddr)) { + /* + * Proxy station only if configured. + */ + if (!ieee80211_mesh_isproxyena(vap)) { + IEEE80211_DISCARD_MAC(vap, + IEEE80211_MSG_OUTPUT | + IEEE80211_MSG_MESH, + eh->ether_dhost, NULL, + "%s", "proxy not enabled"); + vap->iv_stats.is_mesh_notproxy++; + ifp->if_oerrors++; + m_freem(m); + /* XXX better status? */ + return (ENOBUFS); + } + IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT, + "forward frame from DS SA(%6D), DA(%6D)\n", + eh->ether_shost, ":", + eh->ether_dhost, ":"); + ieee80211_mesh_proxy_check(vap, eh->ether_shost); + } + ni = ieee80211_mesh_discover(vap, eh->ether_dhost, m); + if (ni == NULL) { + /* + * NB: ieee80211_mesh_discover holds/disposes + * frame (e.g. queueing on path discovery). + */ + ifp->if_oerrors++; + /* XXX better status? */ + return (ENOBUFS); + } + } +#endif *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201303090139.r291dhG7049757>