[Zrouter-src-freebsd] ZRouter.org: push to FreeBSD HEAD tree
zrouter-src-freebsd at zrouter.org
zrouter-src-freebsd at zrouter.org
Wed Jul 25 14:36:15 UTC 2012
details: http://zrouter.org/hg/FreeBSD/head//rev/4abb4d69799e
changeset: 497:4abb4d69799e
user: Aleksandr Rybalko <ray at ddteam.net>
date: Wed Jul 25 16:47:10 2012 +0300
description:
Lazy update
diffstat:
head/sys/libkern/iconv.c | 13 +-
head/sys/libkern/iconv_ucs.c | 4 +-
head/sys/net/bpf.c | 565 +++++++++++++-------
head/sys/net/bpf.h | 127 ++++-
head/sys/net/bpf_buffer.c | 53 +-
head/sys/net/bpf_buffer.h | 3 +-
head/sys/net/bpf_zerocopy.c | 12 +-
head/sys/net/bpfdesc.h | 15 +-
head/sys/net/flowtable.c | 5 +-
head/sys/net/ieee8023ad_lacp.c | 82 +-
head/sys/net/if.h | 7 +-
head/sys/net/if_bridge.c | 46 +-
head/sys/net/if_dl.h | 3 +-
head/sys/net/if_epair.c | 40 +-
head/sys/net/if_ethersubr.c | 2 +-
head/sys/net/if_gif.c | 139 +++-
head/sys/net/if_lagg.c | 28 +-
head/sys/net/if_loop.c | 27 +-
head/sys/net/if_stf.c | 18 +-
head/sys/net/if_tap.c | 41 +-
head/sys/net/if_var.h | 4 +-
head/sys/net/if_vlan.c | 22 +-
head/sys/net/route.h | 17 +-
head/sys/net/rtsock.c | 6 +-
head/sys/net80211/_ieee80211.h | 4 +-
head/sys/net80211/ieee80211.h | 6 +-
head/sys/net80211/ieee80211_action.c | 10 +-
head/sys/net80211/ieee80211_ddb.c | 6 +-
head/sys/net80211/ieee80211_ht.c | 30 +-
head/sys/net80211/ieee80211_hwmp.c | 878 ++++++++++++++++++++++----------
head/sys/net80211/ieee80211_input.c | 20 +-
head/sys/net80211/ieee80211_ioctl.h | 8 +-
head/sys/net80211/ieee80211_mesh.c | 680 +++++++++++++++++++-----
head/sys/net80211/ieee80211_mesh.h | 109 ++-
head/sys/net80211/ieee80211_output.c | 123 ++-
head/sys/net80211/ieee80211_radiotap.c | 28 +-
head/sys/net80211/ieee80211_var.h | 7 +-
head/sys/netgraph/netflow/netflow.c | 164 +++--
head/sys/netgraph/netflow/netflow_v9.c | 16 +-
head/sys/netgraph/netflow/ng_netflow.c | 83 +--
head/sys/netgraph/netflow/ng_netflow.h | 16 +-
head/sys/netgraph/ng_ksocket.c | 6 +-
head/sys/netgraph/ng_mppc.c | 2 +-
head/sys/netgraph/ng_patch.c | 4 +-
head/sys/netinet6/frag6.c | 15 +-
head/sys/netinet6/icmp6.c | 6 +-
head/sys/netinet6/in6.c | 57 +-
head/sys/netinet6/in6.h | 4 +-
head/sys/netinet6/in6_cksum.c | 120 +++-
head/sys/netinet6/in6_src.c | 6 +-
head/sys/netinet6/ip6_forward.c | 20 +-
head/sys/netinet6/ip6_input.c | 268 ++++++---
head/sys/netinet6/ip6_ipsec.c | 3 +-
head/sys/netinet6/ip6_mroute.c | 32 +-
head/sys/netinet6/ip6_mroute.h | 3 +-
head/sys/netinet6/ip6_output.c | 124 +++-
head/sys/netinet6/ip6_var.h | 6 +-
head/sys/netinet6/mld6.c | 13 +-
head/sys/netinet6/nd6.c | 216 +++----
head/sys/netinet6/nd6.h | 4 +-
head/sys/netinet6/nd6_nbr.c | 14 +-
head/sys/netinet6/route6.c | 4 +-
head/sys/netinet6/scope6.c | 15 +-
head/sys/netinet6/scope6_var.h | 3 +-
head/sys/netinet6/sctp6_usrreq.c | 326 ++++--------
head/sys/netinet6/sctp6_var.h | 11 +-
head/sys/netinet6/udp6_usrreq.c | 23 +-
head/sys/netipsec/ipsec_output.c | 5 +-
head/sys/netncp/ncp_nls.h | 6 +-
head/sys/netsmb/smb_dev.c | 4 +-
head/sys/netsmb/smb_trantcp.c | 6 +-
head/sys/nfsclient/nfs_bio.c | 11 +-
head/sys/nfsclient/nfs_node.c | 4 +-
head/sys/nfsclient/nfs_subs.c | 3 +-
head/sys/nfsclient/nfs_vfsops.c | 3 +-
head/sys/nfsclient/nfs_vnops.c | 18 +-
head/sys/nfsclient/nfsnode.h | 3 +-
77 files changed, 3082 insertions(+), 1753 deletions(-)
diffs (9405 lines):
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/libkern/iconv.c
--- a/head/sys/libkern/iconv.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/libkern/iconv.c Wed Jul 25 16:47:10 2012 +0300
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/libkern/iconv.c 227650 2011-11-18 03:05:20Z kevlo $");
+__FBSDID("$FreeBSD: head/sys/libkern/iconv.c 236899 2012-06-11 17:42:39Z mjg $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -84,9 +84,11 @@
struct iconv_cspair *csp;
sx_xlock(&iconv_lock);
- while ((csp = TAILQ_FIRST(&iconv_cslist)) != NULL) {
- if (csp->cp_refcount)
+ TAILQ_FOREACH(csp, &iconv_cslist, cp_link) {
+ if (csp->cp_refcount) {
+ sx_xunlock(&iconv_lock);
return EBUSY;
+ }
}
while ((csp = TAILQ_FIRST(&iconv_cslist)) != NULL)
@@ -133,6 +135,7 @@
static int
iconv_unregister_converter(struct iconv_converter_class *dcp)
{
+ dcp->refs--;
if (dcp->refs > 1) {
ICDEBUG("converter have %d referenses left\n", dcp->refs);
return EBUSY;
@@ -549,9 +552,7 @@
iconv_lookupcp(char **cpp, const char *s)
{
if (cpp == NULL) {
- ICDEBUG("warning a NULL list passed\n", ""); /* XXX ISO variadic macros cannot
- leave out the
- variadic args */
+ ICDEBUG("warning a NULL list passed\n", "");
return ENOENT;
}
for (; *cpp; cpp++)
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/libkern/iconv_ucs.c
--- a/head/sys/libkern/iconv_ucs.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/libkern/iconv_ucs.c Wed Jul 25 16:47:10 2012 +0300
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/libkern/iconv_ucs.c 227650 2011-11-18 03:05:20Z kevlo $");
+__FBSDID("$FreeBSD: head/sys/libkern/iconv_ucs.c 235713 2012-05-21 02:45:47Z kevlo $");
#include <sys/param.h>
#include <sys/kernel.h>
@@ -457,8 +457,6 @@
/* out of utf-16 range or having illegal bits */
return (0);
}
- if (w == 0)
- return (0);
if (srclen < w)
return (0);
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/net/bpf.c
--- a/head/sys/net/bpf.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/net/bpf.c Wed Jul 25 16:47:10 2012 +0300
@@ -35,7 +35,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/net/bpf.c 233946 2012-04-06 13:34:19Z melifaro $");
+__FBSDID("$FreeBSD: head/sys/net/bpf.c 236806 2012-06-09 10:04:40Z melifaro $");
#include "opt_bpf.h"
#include "opt_compat.h"
@@ -147,6 +147,7 @@
static void bpf_attachd(struct bpf_d *, struct bpf_if *);
static void bpf_detachd(struct bpf_d *);
+static void bpf_detachd_locked(struct bpf_d *);
static void bpf_freed(struct bpf_d *);
static int bpf_movein(struct uio *, int, struct ifnet *, struct mbuf **,
struct sockaddr *, int *, struct bpf_insn *);
@@ -158,7 +159,7 @@
void (*)(struct bpf_d *, caddr_t, u_int, void *, u_int),
struct bintime *);
static void reset_d(struct bpf_d *);
-static int bpf_setf(struct bpf_d *, struct bpf_program *, u_long cmd);
+static int bpf_setf(struct bpf_d *, struct bpf_program *, u_long cmd);
static int bpf_getdltlist(struct bpf_d *, struct bpf_dltlist *);
static int bpf_setdlt(struct bpf_d *, u_int);
static void filt_bpfdetach(struct knote *);
@@ -206,6 +207,37 @@
.f_event = filt_bpfread,
};
+eventhandler_tag bpf_ifdetach_cookie = NULL;
+
+/*
+ * LOCKING MODEL USED BY BPF:
+ * Locks:
+ * 1) global lock (BPF_LOCK). Mutex, used to protect interface addition/removal,
+ * some global counters and every bpf_if reference.
+ * 2) Interface lock. Rwlock, used to protect list of BPF descriptors and their filters.
+ * 3) Descriptor lock. Mutex, used to protect BPF buffers and various structure fields
+ * used by bpf_mtap code.
+ *
+ * Lock order:
+ *
+ * Global lock, interface lock, descriptor lock
+ *
+ * We have to acquire interface lock before descriptor main lock due to BPF_MTAP[2]
+ * working model. In many places (like bpf_detachd) we start with BPF descriptor
+ * (and we need to at least rlock it to get reliable interface pointer). This
+ * gives us potential LOR. As a result, we use global lock to protect from bpf_if
+ * change in every such place.
+ *
+ * Changing d->bd_bif is protected by 1) global lock, 2) interface lock and
+ * 3) descriptor main wlock.
+ * Reading bd_bif can be protected by any of these locks, typically global lock.
+ *
+ * Changing read/write BPF filter is protected by the same three locks,
+ * the same applies for reading.
+ *
+ * Sleeping in global lock is not allowed due to bpfdetach() using it.
+ */
+
/*
* Wrapper functions for various buffering methods. If the set of buffer
* modes expands, we will probably want to introduce a switch data structure
@@ -216,7 +248,7 @@
u_int len)
{
- BPFD_WLOCK_ASSERT(d);
+ BPFD_LOCK_ASSERT(d);
switch (d->bd_bufmode) {
case BPF_BUFMODE_BUFFER:
@@ -236,7 +268,7 @@
u_int len)
{
- BPFD_WLOCK_ASSERT(d);
+ BPFD_LOCK_ASSERT(d);
switch (d->bd_bufmode) {
case BPF_BUFMODE_BUFFER:
@@ -258,7 +290,7 @@
bpf_buf_reclaimed(struct bpf_d *d)
{
- BPFD_WLOCK_ASSERT(d);
+ BPFD_LOCK_ASSERT(d);
switch (d->bd_bufmode) {
case BPF_BUFMODE_BUFFER:
@@ -317,7 +349,7 @@
bpf_buffull(struct bpf_d *d)
{
- BPFD_WLOCK_ASSERT(d);
+ BPFD_LOCK_ASSERT(d);
switch (d->bd_bufmode) {
case BPF_BUFMODE_ZBUF:
@@ -333,7 +365,7 @@
bpf_bufheld(struct bpf_d *d)
{
- BPFD_WLOCK_ASSERT(d);
+ BPFD_LOCK_ASSERT(d);
switch (d->bd_bufmode) {
case BPF_BUFMODE_ZBUF:
@@ -577,6 +609,18 @@
static void
bpf_attachd(struct bpf_d *d, struct bpf_if *bp)
{
+ int op_w;
+
+ BPF_LOCK_ASSERT();
+
+ /*
+ * Save sysctl value to protect from sysctl change
+ * between reads
+ */
+ op_w = V_bpf_optimize_writers;
+
+ if (d->bd_bif != NULL)
+ bpf_detachd_locked(d);
/*
* Point d at bp, and add d to the interface's list.
* Since there are many applicaiotns using BPF for
@@ -584,11 +628,13 @@
* we can delay adding d to the list of active listeners until
* some filter is configured.
*/
+
+ BPFIF_WLOCK(bp);
+ BPFD_LOCK(d);
+
d->bd_bif = bp;
- BPFIF_WLOCK(bp);
-
- if (V_bpf_optimize_writers != 0) {
+ if (op_w != 0) {
/* Add to writers-only list */
LIST_INSERT_HEAD(&bp->bif_wlist, d, bd_next);
/*
@@ -600,16 +646,15 @@
} else
LIST_INSERT_HEAD(&bp->bif_dlist, d, bd_next);
+ BPFD_UNLOCK(d);
BPFIF_WUNLOCK(bp);
- BPF_LOCK();
bpf_bpfd_cnt++;
- BPF_UNLOCK();
CTR3(KTR_NET, "%s: bpf_attach called by pid %d, adding to %s list",
__func__, d->bd_pid, d->bd_writer ? "writer" : "active");
- if (V_bpf_optimize_writers == 0)
+ if (op_w == 0)
EVENTHANDLER_INVOKE(bpf_track, bp->bif_ifp, bp->bif_dlt, 1);
}
@@ -622,10 +667,23 @@
{
struct bpf_if *bp;
+ BPF_LOCK_ASSERT();
+
bp = d->bd_bif;
+ /*
+ * Filter can be set several times without specifying interface.
+ * Mark d as reader and exit.
+ */
+ if (bp == NULL) {
+ BPFD_LOCK(d);
+ d->bd_writer = 0;
+ BPFD_UNLOCK(d);
+ return;
+ }
+
BPFIF_WLOCK(bp);
- BPFD_WLOCK(d);
+ BPFD_LOCK(d);
/* Remove from writers-only list */
LIST_REMOVE(d, bd_next);
@@ -633,7 +691,7 @@
/* Mark d as reader */
d->bd_writer = 0;
- BPFD_WUNLOCK(d);
+ BPFD_UNLOCK(d);
BPFIF_WUNLOCK(bp);
CTR2(KTR_NET, "%s: upgrade required by pid %d", __func__, d->bd_pid);
@@ -647,6 +705,14 @@
static void
bpf_detachd(struct bpf_d *d)
{
+ BPF_LOCK();
+ bpf_detachd_locked(d);
+ BPF_UNLOCK();
+}
+
+static void
+bpf_detachd_locked(struct bpf_d *d)
+{
int error;
struct bpf_if *bp;
struct ifnet *ifp;
@@ -655,9 +721,12 @@
BPF_LOCK_ASSERT();
- bp = d->bd_bif;
+ /* Check if descriptor is attached */
+ if ((bp = d->bd_bif) == NULL)
+ return;
+
BPFIF_WLOCK(bp);
- BPFD_WLOCK(d);
+ BPFD_LOCK(d);
/* Save bd_writer value */
error = d->bd_writer;
@@ -669,10 +738,9 @@
ifp = bp->bif_ifp;
d->bd_bif = NULL;
- BPFD_WUNLOCK(d);
+ BPFD_UNLOCK(d);
BPFIF_WUNLOCK(bp);
- /* We're already protected by global lock. */
bpf_bpfd_cnt--;
/* Call event handler iff d is attached */
@@ -710,16 +778,13 @@
{
struct bpf_d *d = data;
- BPFD_WLOCK(d);
+ BPFD_LOCK(d);
if (d->bd_state == BPF_WAITING)
callout_stop(&d->bd_callout);
d->bd_state = BPF_IDLE;
- BPFD_WUNLOCK(d);
+ BPFD_UNLOCK(d);
funsetown(&d->bd_sigio);
- BPF_LOCK();
- if (d->bd_bif)
- bpf_detachd(d);
- BPF_UNLOCK();
+ bpf_detachd(d);
#ifdef MAC
mac_bpfdesc_destroy(d);
#endif /* MAC */
@@ -739,7 +804,7 @@
bpfopen(struct cdev *dev, int flags, int fmt, struct thread *td)
{
struct bpf_d *d;
- int error;
+ int error, size;
d = malloc(sizeof(*d), M_BPF, M_WAITOK | M_ZERO);
error = devfs_set_cdevpriv(d, bpf_dtor);
@@ -762,9 +827,13 @@
mac_bpfdesc_init(d);
mac_bpfdesc_create(td->td_ucred, d);
#endif
- rw_init(&d->bd_lock, "bpf cdev lock");
- callout_init_rw(&d->bd_callout, &d->bd_lock, 0);
- knlist_init_rw_reader(&d->bd_sel.si_note, &d->bd_lock);
+ mtx_init(&d->bd_lock, devtoname(dev), "bpf cdev lock", MTX_DEF);
+ callout_init_mtx(&d->bd_callout, &d->bd_lock, 0);
+ knlist_init_mtx(&d->bd_sel.si_note, &d->bd_lock);
+
+ /* Allocate default buffers */
+ size = d->bd_bufsize;
+ bpf_buffer_ioctl_sblen(d, &size);
return (0);
}
@@ -793,10 +862,10 @@
non_block = ((ioflag & O_NONBLOCK) != 0);
- BPFD_WLOCK(d);
+ BPFD_LOCK(d);
BPF_PID_REFRESH_CUR(d);
if (d->bd_bufmode != BPF_BUFMODE_BUFFER) {
- BPFD_WUNLOCK(d);
+ BPFD_UNLOCK(d);
return (EOPNOTSUPP);
}
if (d->bd_state == BPF_WAITING)
@@ -832,18 +901,18 @@
* it before using it again.
*/
if (d->bd_bif == NULL) {
- BPFD_WUNLOCK(d);
+ BPFD_UNLOCK(d);
return (ENXIO);
}
if (non_block) {
- BPFD_WUNLOCK(d);
+ BPFD_UNLOCK(d);
return (EWOULDBLOCK);
}
- error = rw_sleep(d, &d->bd_lock, PRINET|PCATCH,
+ error = msleep(d, &d->bd_lock, PRINET|PCATCH,
"bpf", d->bd_rtout);
if (error == EINTR || error == ERESTART) {
- BPFD_WUNLOCK(d);
+ BPFD_UNLOCK(d);
return (error);
}
if (error == EWOULDBLOCK) {
@@ -861,7 +930,7 @@
break;
if (d->bd_slen == 0) {
- BPFD_WUNLOCK(d);
+ BPFD_UNLOCK(d);
return (0);
}
ROTATE_BUFFERS(d);
@@ -871,7 +940,7 @@
/*
* At this point, we know we have something in the hold slot.
*/
- BPFD_WUNLOCK(d);
+ BPFD_UNLOCK(d);
/*
* Move data from hold buffer into user space.
@@ -884,12 +953,12 @@
*/
error = bpf_uiomove(d, d->bd_hbuf, d->bd_hlen, uio);
- BPFD_WLOCK(d);
+ BPFD_LOCK(d);
d->bd_fbuf = d->bd_hbuf;
d->bd_hbuf = NULL;
d->bd_hlen = 0;
bpf_buf_reclaimed(d);
- BPFD_WUNLOCK(d);
+ BPFD_UNLOCK(d);
return (error);
}
@@ -901,7 +970,7 @@
bpf_wakeup(struct bpf_d *d)
{
- BPFD_WLOCK_ASSERT(d);
+ BPFD_LOCK_ASSERT(d);
if (d->bd_state == BPF_WAITING) {
callout_stop(&d->bd_callout);
d->bd_state = BPF_IDLE;
@@ -919,7 +988,7 @@
{
struct bpf_d *d = (struct bpf_d *)arg;
- BPFD_WLOCK_ASSERT(d);
+ BPFD_LOCK_ASSERT(d);
if (callout_pending(&d->bd_callout) || !callout_active(&d->bd_callout))
return;
@@ -934,7 +1003,7 @@
bpf_ready(struct bpf_d *d)
{
- BPFD_WLOCK_ASSERT(d);
+ BPFD_LOCK_ASSERT(d);
if (!bpf_canfreebuf(d) && d->bd_hlen != 0)
return (1);
@@ -959,6 +1028,7 @@
BPF_PID_REFRESH_CUR(d);
d->bd_wcount++;
+ /* XXX: locking required */
if (d->bd_bif == NULL) {
d->bd_wdcount++;
return (ENXIO);
@@ -979,6 +1049,7 @@
bzero(&dst, sizeof(dst));
m = NULL;
hlen = 0;
+ /* XXX: bpf_movein() can sleep */
error = bpf_movein(uio, (int)d->bd_bif->bif_dlt, ifp,
&m, &dst, &hlen, d->bd_wfilter);
if (error) {
@@ -1005,11 +1076,11 @@
CURVNET_SET(ifp->if_vnet);
#ifdef MAC
- BPFD_WLOCK(d);
+ BPFD_LOCK(d);
mac_bpfdesc_create_mbuf(d, m);
if (mc != NULL)
mac_bpfdesc_create_mbuf(d, mc);
- BPFD_WUNLOCK(d);
+ BPFD_UNLOCK(d);
#endif
error = (*ifp->if_output)(ifp, m, &dst, NULL);
@@ -1038,7 +1109,7 @@
reset_d(struct bpf_d *d)
{
- BPFD_WLOCK_ASSERT(d);
+ BPFD_LOCK_ASSERT(d);
if ((d->bd_hbuf != NULL) &&
(d->bd_bufmode != BPF_BUFMODE_ZBUF || bpf_canfreebuf(d))) {
@@ -1105,12 +1176,12 @@
/*
* Refresh PID associated with this descriptor.
*/
- BPFD_WLOCK(d);
+ BPFD_LOCK(d);
BPF_PID_REFRESH(d, td);
if (d->bd_state == BPF_WAITING)
callout_stop(&d->bd_callout);
d->bd_state = BPF_IDLE;
- BPFD_WUNLOCK(d);
+ BPFD_UNLOCK(d);
if (d->bd_locked == 1) {
switch (cmd) {
@@ -1158,7 +1229,9 @@
case BIOCGDLTLIST32:
case BIOCGRTIMEOUT32:
case BIOCSRTIMEOUT32:
+ BPFD_LOCK(d);
d->bd_compat32 = 1;
+ BPFD_UNLOCK(d);
}
#endif
@@ -1176,11 +1249,11 @@
{
int n;
- BPFD_WLOCK(d);
+ BPFD_LOCK(d);
n = d->bd_slen;
if (d->bd_hbuf)
n += d->bd_hlen;
- BPFD_WUNLOCK(d);
+ BPFD_UNLOCK(d);
*(int *)addr = n;
break;
@@ -1203,7 +1276,9 @@
* Get buffer len [for read()].
*/
case BIOCGBLEN:
+ BPFD_LOCK(d);
*(u_int *)addr = d->bd_bufsize;
+ BPFD_UNLOCK(d);
break;
/*
@@ -1231,9 +1306,9 @@
* Flush read packet buffer.
*/
case BIOCFLUSH:
- BPFD_WLOCK(d);
+ BPFD_LOCK(d);
reset_d(d);
- BPFD_WUNLOCK(d);
+ BPFD_UNLOCK(d);
break;
/*
@@ -1258,10 +1333,12 @@
* Get current data link type.
*/
case BIOCGDLT:
+ BPF_LOCK();
if (d->bd_bif == NULL)
error = EINVAL;
else
*(u_int *)addr = d->bd_bif->bif_dlt;
+ BPF_UNLOCK();
break;
/*
@@ -1276,6 +1353,7 @@
list32 = (struct bpf_dltlist32 *)addr;
dltlist.bfl_len = list32->bfl_len;
dltlist.bfl_list = PTRIN(list32->bfl_list);
+ BPF_LOCK();
if (d->bd_bif == NULL)
error = EINVAL;
else {
@@ -1283,31 +1361,37 @@
if (error == 0)
list32->bfl_len = dltlist.bfl_len;
}
+ BPF_UNLOCK();
break;
}
#endif
case BIOCGDLTLIST:
+ BPF_LOCK();
if (d->bd_bif == NULL)
error = EINVAL;
else
error = bpf_getdltlist(d, (struct bpf_dltlist *)addr);
+ BPF_UNLOCK();
break;
/*
* Set data link type.
*/
case BIOCSDLT:
+ BPF_LOCK();
if (d->bd_bif == NULL)
error = EINVAL;
else
error = bpf_setdlt(d, *(u_int *)addr);
+ BPF_UNLOCK();
break;
/*
* Get interface name.
*/
case BIOCGETIF:
+ BPF_LOCK();
if (d->bd_bif == NULL)
error = EINVAL;
else {
@@ -1317,13 +1401,16 @@
strlcpy(ifr->ifr_name, ifp->if_xname,
sizeof(ifr->ifr_name));
}
+ BPF_UNLOCK();
break;
/*
* Set interface.
*/
case BIOCSETIF:
+ BPF_LOCK();
error = bpf_setif(d, (struct ifreq *)addr);
+ BPF_UNLOCK();
break;
/*
@@ -1406,7 +1493,9 @@
* Set immediate mode.
*/
case BIOCIMMEDIATE:
+ BPFD_LOCK(d);
d->bd_immediate = *(u_int *)addr;
+ BPFD_UNLOCK(d);
break;
case BIOCVERSION:
@@ -1422,21 +1511,27 @@
* Get "header already complete" flag
*/
case BIOCGHDRCMPLT:
+ BPFD_LOCK(d);
*(u_int *)addr = d->bd_hdrcmplt;
+ BPFD_UNLOCK(d);
break;
/*
* Set "header already complete" flag
*/
case BIOCSHDRCMPLT:
+ BPFD_LOCK(d);
d->bd_hdrcmplt = *(u_int *)addr ? 1 : 0;
+ BPFD_UNLOCK(d);
break;
/*
* Get packet direction flag
*/
case BIOCGDIRECTION:
+ BPFD_LOCK(d);
*(u_int *)addr = d->bd_direction;
+ BPFD_UNLOCK(d);
break;
/*
@@ -1451,7 +1546,9 @@
case BPF_D_IN:
case BPF_D_INOUT:
case BPF_D_OUT:
+ BPFD_LOCK(d);
d->bd_direction = direction;
+ BPFD_UNLOCK(d);
break;
default:
error = EINVAL;
@@ -1463,7 +1560,9 @@
* Get packet timestamp format and resolution.
*/
case BIOCGTSTAMP:
+ BPFD_LOCK(d);
*(u_int *)addr = d->bd_tstamp;
+ BPFD_UNLOCK(d);
break;
/*
@@ -1482,26 +1581,38 @@
break;
case BIOCFEEDBACK:
+ BPFD_LOCK(d);
d->bd_feedback = *(u_int *)addr;
+ BPFD_UNLOCK(d);
break;
case BIOCLOCK:
+ BPFD_LOCK(d);
d->bd_locked = 1;
+ BPFD_UNLOCK(d);
break;
case FIONBIO: /* Non-blocking I/O */
break;
case FIOASYNC: /* Send signal on receive packets */
+ BPFD_LOCK(d);
d->bd_async = *(int *)addr;
+ BPFD_UNLOCK(d);
break;
case FIOSETOWN:
+ /*
+ * XXX: Add some sort of locking here?
+ * fsetown() can sleep.
+ */
error = fsetown(*(int *)addr, &d->bd_sigio);
break;
case FIOGETOWN:
+ BPFD_LOCK(d);
*(int *)addr = fgetown(&d->bd_sigio);
+ BPFD_UNLOCK(d);
break;
/* This is deprecated, FIOSETOWN should be used instead. */
@@ -1522,16 +1633,23 @@
if (sig >= NSIG)
error = EINVAL;
- else
+ else {
+ BPFD_LOCK(d);
d->bd_sig = sig;
+ BPFD_UNLOCK(d);
+ }
break;
}
case BIOCGRSIG:
+ BPFD_LOCK(d);
*(u_int *)addr = d->bd_sig;
+ BPFD_UNLOCK(d);
break;
case BIOCGETBUFMODE:
+ BPFD_LOCK(d);
*(u_int *)addr = d->bd_bufmode;
+ BPFD_UNLOCK(d);
break;
case BIOCSETBUFMODE:
@@ -1556,15 +1674,15 @@
return (EINVAL);
}
- BPFD_WLOCK(d);
+ BPFD_LOCK(d);
if (d->bd_sbuf != NULL || d->bd_hbuf != NULL ||
d->bd_fbuf != NULL || d->bd_bif != NULL) {
- BPFD_WUNLOCK(d);
+ BPFD_UNLOCK(d);
CURVNET_RESTORE();
return (EBUSY);
}
d->bd_bufmode = *(u_int *)addr;
- BPFD_WUNLOCK(d);
+ BPFD_UNLOCK(d);
break;
case BIOCGETZMAX:
@@ -1586,123 +1704,130 @@
/*
* Set d's packet filter program to fp. If this file already has a filter,
* free it and replace it. Returns EINVAL for bogus requests.
+ *
+ * Note we need global lock here to serialize bpf_setf() and bpf_setif() calls
+ * since reading d->bd_bif can't be protected by d or interface lock due to
+ * lock order.
+ *
+ * Additionally, we have to acquire interface write lock due to bpf_mtap() uses
+ * interface read lock to read all filers.
+ *
*/
static int
bpf_setf(struct bpf_d *d, struct bpf_program *fp, u_long cmd)
{
+#ifdef COMPAT_FREEBSD32
+ struct bpf_program fp_swab;
+ struct bpf_program32 *fp32;
+#endif
struct bpf_insn *fcode, *old;
- u_int wfilter, flen, size;
#ifdef BPF_JITTER
- bpf_jit_filter *ofunc;
+ bpf_jit_filter *jfunc, *ofunc;
#endif
+ size_t size;
+ u_int flen;
int need_upgrade;
+
#ifdef COMPAT_FREEBSD32
- struct bpf_program32 *fp32;
- struct bpf_program fp_swab;
-
- if (cmd == BIOCSETWF32 || cmd == BIOCSETF32 || cmd == BIOCSETFNR32) {
+ switch (cmd) {
+ case BIOCSETF32:
+ case BIOCSETWF32:
+ case BIOCSETFNR32:
fp32 = (struct bpf_program32 *)fp;
fp_swab.bf_len = fp32->bf_len;
fp_swab.bf_insns = (struct bpf_insn *)(uintptr_t)fp32->bf_insns;
fp = &fp_swab;
- if (cmd == BIOCSETWF32)
+ switch (cmd) {
+ case BIOCSETF32:
+ cmd = BIOCSETF;
+ break;
+ case BIOCSETWF32:
cmd = BIOCSETWF;
+ break;
+ }
+ break;
}
#endif
+
+ fcode = NULL;
+#ifdef BPF_JITTER
+ jfunc = ofunc = NULL;
+#endif
+ need_upgrade = 0;
+
+ /*
+ * Check new filter validness before acquiring any locks.
+ * Allocate memory for new filter, if needed.
+ */
+ flen = fp->bf_len;
+ if (flen > bpf_maxinsns || (fp->bf_insns == NULL && flen != 0))
+ return (EINVAL);
+ size = flen * sizeof(*fp->bf_insns);
+ if (size > 0) {
+ /* We're setting up new filter. Copy and check actual data. */
+ fcode = malloc(size, M_BPF, M_WAITOK);
+ if (copyin(fp->bf_insns, fcode, size) != 0 ||
+ !bpf_validate(fcode, flen)) {
+ free(fcode, M_BPF);
+ return (EINVAL);
+ }
+#ifdef BPF_JITTER
+ /* Filter is copied inside fcode and is perfectly valid. */
+ jfunc = bpf_jitter(fcode, flen);
+#endif
+ }
+
+ BPF_LOCK();
+
+ /*
+ * Set up new filter.
+ * Protect filter change by interface lock.
+ * Additionally, we are protected by global lock here.
+ */
+ if (d->bd_bif != NULL)
+ BPFIF_WLOCK(d->bd_bif);
+ BPFD_LOCK(d);
if (cmd == BIOCSETWF) {
old = d->bd_wfilter;
- wfilter = 1;
-#ifdef BPF_JITTER
- ofunc = NULL;
-#endif
+ d->bd_wfilter = fcode;
} else {
- wfilter = 0;
old = d->bd_rfilter;
+ d->bd_rfilter = fcode;
#ifdef BPF_JITTER
ofunc = d->bd_bfilter;
+ d->bd_bfilter = jfunc;
#endif
- }
- if (fp->bf_insns == NULL) {
- if (fp->bf_len != 0)
- return (EINVAL);
- /*
- * Protect filter change by interface lock, too.
- * The same lock order is used by bpf_detachd().
- */
- BPFIF_WLOCK(d->bd_bif);
- BPFD_WLOCK(d);
- if (wfilter)
- d->bd_wfilter = NULL;
- else {
- d->bd_rfilter = NULL;
-#ifdef BPF_JITTER
- d->bd_bfilter = NULL;
-#endif
- if (cmd == BIOCSETF)
- reset_d(d);
- }
- BPFD_WUNLOCK(d);
- BPFIF_WUNLOCK(d->bd_bif);
- if (old != NULL)
- free((caddr_t)old, M_BPF);
-#ifdef BPF_JITTER
- if (ofunc != NULL)
- bpf_destroy_jit_filter(ofunc);
-#endif
- return (0);
- }
- flen = fp->bf_len;
- if (flen > bpf_maxinsns)
- return (EINVAL);
-
- need_upgrade = 0;
- size = flen * sizeof(*fp->bf_insns);
- fcode = (struct bpf_insn *)malloc(size, M_BPF, M_WAITOK);
- if (copyin((caddr_t)fp->bf_insns, (caddr_t)fcode, size) == 0 &&
- bpf_validate(fcode, (int)flen)) {
- /*
- * Protect filter change by interface lock, too
- * The same lock order is used by bpf_detachd().
- */
- BPFIF_WLOCK(d->bd_bif);
- BPFD_WLOCK(d);
- if (wfilter)
- d->bd_wfilter = fcode;
- else {
- d->bd_rfilter = fcode;
-#ifdef BPF_JITTER
- d->bd_bfilter = bpf_jitter(fcode, flen);
-#endif
- if (cmd == BIOCSETF)
- reset_d(d);
-
+ if (cmd == BIOCSETF)
+ reset_d(d);
+
+ if (fcode != NULL) {
/*
* Do not require upgrade by first BIOCSETF
- * (used to set snaplen) by pcap_open_live()
+ * (used to set snaplen) by pcap_open_live().
*/
- if ((d->bd_writer != 0) && (--d->bd_writer == 0))
+ if (d->bd_writer != 0 && --d->bd_writer == 0)
need_upgrade = 1;
CTR4(KTR_NET, "%s: filter function set by pid %d, "
"bd_writer counter %d, need_upgrade %d",
__func__, d->bd_pid, d->bd_writer, need_upgrade);
}
- BPFD_WUNLOCK(d);
+ }
+ BPFD_UNLOCK(d);
+ if (d->bd_bif != NULL)
BPFIF_WUNLOCK(d->bd_bif);
- if (old != NULL)
- free((caddr_t)old, M_BPF);
+ if (old != NULL)
+ free(old, M_BPF);
#ifdef BPF_JITTER
- if (ofunc != NULL)
- bpf_destroy_jit_filter(ofunc);
+ if (ofunc != NULL)
+ bpf_destroy_jit_filter(ofunc);
#endif
- /* Move d to active readers list */
- if (need_upgrade != 0)
- bpf_upgraded(d);
-
- return (0);
- }
- free((caddr_t)fcode, M_BPF);
- return (EINVAL);
+ /* Move d to active readers list. */
+ if (need_upgrade)
+ bpf_upgraded(d);
+
+ BPF_UNLOCK();
+ return (0);
}
/*
@@ -1716,28 +1841,30 @@
struct bpf_if *bp;
struct ifnet *theywant;
+ BPF_LOCK_ASSERT();
+
theywant = ifunit(ifr->ifr_name);
if (theywant == NULL || theywant->if_bpf == NULL)
return (ENXIO);
bp = theywant->if_bpf;
+ /* Check if interface is not being detached from BPF */
+ BPFIF_RLOCK(bp);
+ if (bp->flags & BPFIF_FLAG_DYING) {
+ BPFIF_RUNLOCK(bp);
+ return (ENXIO);
+ }
+ BPFIF_RUNLOCK(bp);
+
/*
* Behavior here depends on the buffering model. If we're using
* kernel memory buffers, then we can allocate them here. If we're
* using zero-copy, then the user process must have registered
* buffers by the time we get here. If not, return an error.
- *
- * XXXRW: There are locking issues here with multi-threaded use: what
- * if two threads try to set the interface at once?
*/
switch (d->bd_bufmode) {
case BPF_BUFMODE_BUFFER:
- if (d->bd_sbuf == NULL)
- bpf_buffer_alloc(d);
- KASSERT(d->bd_sbuf != NULL, ("bpf_setif: bd_sbuf NULL"));
- break;
-
case BPF_BUFMODE_ZBUF:
if (d->bd_sbuf == NULL)
return (EINVAL);
@@ -1746,18 +1873,11 @@
default:
panic("bpf_setif: bufmode %d", d->bd_bufmode);
}
- if (bp != d->bd_bif) {
- if (d->bd_bif)
- /*
- * Detach if attached to something else.
- */
- bpf_detachd(d);
-
+ if (bp != d->bd_bif)
bpf_attachd(d, bp);
- }
- BPFD_WLOCK(d);
+ BPFD_LOCK(d);
reset_d(d);
- BPFD_WUNLOCK(d);
+ BPFD_UNLOCK(d);
return (0);
}
@@ -1781,7 +1901,7 @@
* Refresh PID associated with this descriptor.
*/
revents = events & (POLLOUT | POLLWRNORM);
- BPFD_WLOCK(d);
+ BPFD_LOCK(d);
BPF_PID_REFRESH(d, td);
if (events & (POLLIN | POLLRDNORM)) {
if (bpf_ready(d))
@@ -1796,7 +1916,7 @@
}
}
}
- BPFD_WUNLOCK(d);
+ BPFD_UNLOCK(d);
return (revents);
}
@@ -1816,12 +1936,12 @@
/*
* Refresh PID associated with this descriptor.
*/
- BPFD_WLOCK(d);
+ BPFD_LOCK(d);
BPF_PID_REFRESH_CUR(d);
kn->kn_fop = &bpfread_filtops;
kn->kn_hook = d;
knlist_add(&d->bd_sel.si_note, kn, 1);
- BPFD_WUNLOCK(d);
+ BPFD_UNLOCK(d);
return (0);
}
@@ -1840,7 +1960,7 @@
struct bpf_d *d = (struct bpf_d *)kn->kn_hook;
int ready;
- BPFD_WLOCK_ASSERT(d);
+ BPFD_LOCK_ASSERT(d);
ready = bpf_ready(d);
if (ready) {
kn->kn_data = d->bd_slen;
@@ -1946,7 +2066,7 @@
/*
* Filter matches. Let's to acquire write lock.
*/
- BPFD_WLOCK(d);
+ BPFD_LOCK(d);
d->bd_fcount++;
if (gottime < bpf_ts_quality(d->bd_tstamp))
@@ -1956,7 +2076,7 @@
#endif
catchpacket(d, pkt, pktlen, slen,
bpf_append_bytes, &bt);
- BPFD_WUNLOCK(d);
+ BPFD_UNLOCK(d);
}
}
BPFIF_RUNLOCK(bp);
@@ -2005,7 +2125,7 @@
#endif
slen = bpf_filter(d->bd_rfilter, (u_char *)m, pktlen, 0);
if (slen != 0) {
- BPFD_WLOCK(d);
+ BPFD_LOCK(d);
d->bd_fcount++;
if (gottime < bpf_ts_quality(d->bd_tstamp))
@@ -2015,7 +2135,7 @@
#endif
catchpacket(d, (u_char *)m, pktlen, slen,
bpf_append_mbuf, &bt);
- BPFD_WUNLOCK(d);
+ BPFD_UNLOCK(d);
}
}
BPFIF_RUNLOCK(bp);
@@ -2061,7 +2181,7 @@
++d->bd_rcount;
slen = bpf_filter(d->bd_rfilter, (u_char *)&mb, pktlen, 0);
if (slen != 0) {
- BPFD_WLOCK(d);
+ BPFD_LOCK(d);
d->bd_fcount++;
if (gottime < bpf_ts_quality(d->bd_tstamp))
@@ -2071,7 +2191,7 @@
#endif
catchpacket(d, (u_char *)&mb, pktlen, slen,
bpf_append_mbuf, &bt);
- BPFD_WUNLOCK(d);
+ BPFD_UNLOCK(d);
}
}
BPFIF_RUNLOCK(bp);
@@ -2166,7 +2286,7 @@
int do_timestamp;
int tstype;
- BPFD_WLOCK_ASSERT(d);
+ BPFD_LOCK_ASSERT(d);
/*
* Detect whether user space has released a buffer back to us, and if
@@ -2313,7 +2433,7 @@
}
if (d->bd_wfilter != NULL)
free((caddr_t)d->bd_wfilter, M_BPF);
- rw_destroy(&d->bd_lock);
+ mtx_destroy(&d->bd_lock);
}
/*
@@ -2361,10 +2481,9 @@
}
/*
- * Detach bpf from an interface. This involves detaching each descriptor
- * associated with the interface, and leaving bd_bif NULL. Notify each
- * descriptor as it's detached so that any sleepers wake up and get
- * ENXIO.
+ * Detach bpf from an interface. This involves detaching each descriptor
+ * associated with the interface. Notify each descriptor as it's detached
+ * so that any sleepers wake up and get ENXIO.
*/
void
bpfdetach(struct ifnet *ifp)
@@ -2377,31 +2496,45 @@
ndetached = 0;
#endif
+ BPF_LOCK();
/* Find all bpf_if struct's which reference ifp and detach them. */
do {
- BPF_LOCK();
LIST_FOREACH(bp, &bpf_iflist, bif_next) {
if (ifp == bp->bif_ifp)
break;
}
if (bp != NULL)
LIST_REMOVE(bp, bif_next);
- BPF_UNLOCK();
if (bp != NULL) {
#ifdef INVARIANTS
ndetached++;
#endif
while ((d = LIST_FIRST(&bp->bif_dlist)) != NULL) {
- bpf_detachd(d);
- BPFD_WLOCK(d);
+ bpf_detachd_locked(d);
+ BPFD_LOCK(d);
bpf_wakeup(d);
- BPFD_WUNLOCK(d);
+ BPFD_UNLOCK(d);
}
- rw_destroy(&bp->bif_lock);
- free(bp, M_BPF);
+ /* Free writer-only descriptors */
+ while ((d = LIST_FIRST(&bp->bif_wlist)) != NULL) {
+ bpf_detachd_locked(d);
+ BPFD_LOCK(d);
+ bpf_wakeup(d);
+ BPFD_UNLOCK(d);
+ }
+
+ /*
+ * Delay freing bp till interface is detached
+ * and all routes through this interface are removed.
+ * Mark bp as detached to restrict new consumers.
+ */
+ BPFIF_WLOCK(bp);
+ bp->flags |= BPFIF_FLAG_DYING;
+ BPFIF_WUNLOCK(bp);
}
} while (bp != NULL);
+ BPF_UNLOCK();
#ifdef INVARIANTS
if (ndetached == 0)
@@ -2410,6 +2543,37 @@
}
/*
+ * Interface departure handler.
+ * Note departure event does not guarantee interface is going down.
+ */
+static void
+bpf_ifdetach(void *arg __unused, struct ifnet *ifp)
+{
+ struct bpf_if *bp;
+
+ BPF_LOCK();
+ if ((bp = ifp->if_bpf) == NULL) {
+ BPF_UNLOCK();
+ return;
+ }
+
+ /* Check if bpfdetach() was called previously */
+ if ((bp->flags & BPFIF_FLAG_DYING) == 0) {
+ BPF_UNLOCK();
+ return;
+ }
+
+ CTR3(KTR_NET, "%s: freing BPF instance %p for interface %p",
+ __func__, bp, ifp);
+
+ ifp->if_bpf = NULL;
+ BPF_UNLOCK();
+
+ rw_destroy(&bp->bif_lock);
+ free(bp, M_BPF);
+}
+
+/*
* Get a list of available data link type of the interface.
*/
static int
@@ -2419,24 +2583,22 @@
struct ifnet *ifp;
struct bpf_if *bp;
+ BPF_LOCK_ASSERT();
+
ifp = d->bd_bif->bif_ifp;
n = 0;
error = 0;
- BPF_LOCK();
LIST_FOREACH(bp, &bpf_iflist, bif_next) {
if (bp->bif_ifp != ifp)
continue;
if (bfl->bfl_list != NULL) {
- if (n >= bfl->bfl_len) {
- BPF_UNLOCK();
+ if (n >= bfl->bfl_len)
return (ENOMEM);
- }
error = copyout(&bp->bif_dlt,
bfl->bfl_list + n, sizeof(u_int));
}
n++;
}
- BPF_UNLOCK();
bfl->bfl_len = n;
return (error);
}
@@ -2451,22 +2613,23 @@
struct ifnet *ifp;
struct bpf_if *bp;
+ BPF_LOCK_ASSERT();
+
if (d->bd_bif->bif_dlt == dlt)
return (0);
ifp = d->bd_bif->bif_ifp;
- BPF_LOCK();
+
LIST_FOREACH(bp, &bpf_iflist, bif_next) {
if (bp->bif_ifp == ifp && bp->bif_dlt == dlt)
break;
}
- BPF_UNLOCK();
+
if (bp != NULL) {
opromisc = d->bd_promisc;
- bpf_detachd(d);
bpf_attachd(d, bp);
- BPFD_WLOCK(d);
+ BPFD_LOCK(d);
reset_d(d);
- BPFD_WUNLOCK(d);
+ BPFD_UNLOCK(d);
if (opromisc) {
error = ifpromisc(bp->bif_ifp, 1);
if (error)
@@ -2491,6 +2654,11 @@
dev = make_dev(&bpf_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "bpf");
/* For compatibility */
make_dev_alias(dev, "bpf0");
+
+ /* Register interface departure handler */
+ bpf_ifdetach_cookie = EVENTHANDLER_REGISTER(
+ ifnet_departure_event, bpf_ifdetach, NULL,
+ EVENTHANDLER_PRI_ANY);
}
/*
@@ -2508,20 +2676,23 @@
LIST_FOREACH(bp, &bpf_iflist, bif_next) {
BPFIF_RLOCK(bp);
LIST_FOREACH(bd, &bp->bif_dlist, bd_next) {
- BPFD_WLOCK(bd);
+ BPFD_LOCK(bd);
bd->bd_rcount = 0;
bd->bd_dcount = 0;
bd->bd_fcount = 0;
bd->bd_wcount = 0;
bd->bd_wfcount = 0;
bd->bd_zcopy = 0;
- BPFD_WUNLOCK(bd);
+ BPFD_UNLOCK(bd);
}
BPFIF_RUNLOCK(bp);
}
BPF_UNLOCK();
}
+/*
+ * Fill filter statistics
+ */
static void
bpfstats_fill_xbpf(struct xbpf_d *d, struct bpf_d *bd)
{
@@ -2529,6 +2700,7 @@
bzero(d, sizeof(*d));
BPFD_LOCK_ASSERT(bd);
d->bd_structsize = sizeof(*d);
+ /* XXX: reading should be protected by global lock */
d->bd_immediate = bd->bd_immediate;
d->bd_promisc = bd->bd_promisc;
d->bd_hdrcmplt = bd->bd_hdrcmplt;
@@ -2553,6 +2725,9 @@
d->bd_bufmode = bd->bd_bufmode;
}
+/*
+ * Handle `netstat -B' stats request
+ */
static int
bpf_stats_sysctl(SYSCTL_HANDLER_ARGS)
{
@@ -2602,15 +2777,15 @@
/* Send writers-only first */
LIST_FOREACH(bd, &bp->bif_wlist, bd_next) {
xbd = &xbdbuf[index++];
- BPFD_RLOCK(bd);
+ BPFD_LOCK(bd);
bpfstats_fill_xbpf(xbd, bd);
- BPFD_RUNLOCK(bd);
+ BPFD_UNLOCK(bd);
}
LIST_FOREACH(bd, &bp->bif_dlist, bd_next) {
xbd = &xbdbuf[index++];
- BPFD_RLOCK(bd);
+ BPFD_LOCK(bd);
bpfstats_fill_xbpf(xbd, bd);
- BPFD_RUNLOCK(bd);
+ BPFD_UNLOCK(bd);
}
BPFIF_RUNLOCK(bp);
}
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/net/bpf.h
--- a/head/sys/net/bpf.h Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/net/bpf.h Wed Jul 25 16:47:10 2012 +0300
@@ -34,7 +34,7 @@
* @(#)bpf.h 8.1 (Berkeley) 6/10/93
* @(#)bpf.h 1.34 (LBL) 6/16/96
*
- * $FreeBSD: head/sys/net/bpf.h 233938 2012-04-06 06:55:21Z melifaro $
+ * $FreeBSD: head/sys/net/bpf.h 235745 2012-05-21 22:17:29Z melifaro $
*/
#ifndef _NET_BPF_H_
@@ -279,6 +279,24 @@
*/
#define DLT_SYMANTEC_FIREWALL 99
+/*
+ * Values between 100 and 103 are used in capture file headers as
+ * link-layer header type LINKTYPE_ values corresponding to DLT_ types
+ * that differ between platforms; don't use those values for new DLT_
+ * new types.
+ */
+
+/*
+ * Values starting with 104 are used for newly-assigned link-layer
+ * header type values; for those link-layer header types, the DLT_
+ * value returned by pcap_datalink() and passed to pcap_open_dead(),
+ * and the LINKTYPE_ value that appears in capture files, are the
+ * same.
+ *
+ * DLT_MATCHING_MIN is the lowest such value; DLT_MATCHING_MAX is
+ * the highest such value.
+ */
+#define DLT_MATCHING_MIN 104
/*
* This value was defined by libpcap 0.5; platforms that have defined
@@ -978,8 +996,110 @@
* Raw IPv4/IPv6; different from DLT_RAW in that the DLT_ value specifies
* whether it's v4 or v6. Requested by Darren Reed <Darren.Reed at Sun.COM>.
*/
-#define DLT_IPV4 228
-#define DLT_IPV6 229
+#define DLT_IPV4 228
+#define DLT_IPV6 229
+
+/*
+ * IEEE 802.15.4, exactly as it appears in the spec (no padding, no
+ * nothing), and with no FCS at the end of the frame; requested by
+ * Jon Smirl <jonsmirl at gmail.com>.
+ */
+#define DLT_IEEE802_15_4_NOFCS 230
+
+/*
+ * Raw D-Bus:
+ *
+ * http://www.freedesktop.org/wiki/Software/dbus
+ *
+ * messages:
+ *
+ * http://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-messages
+ *
+ * starting with the endianness flag, followed by the message type, etc.,
+ * but without the authentication handshake before the message sequence:
+ *
+ * http://dbus.freedesktop.org/doc/dbus-specification.html#auth-protocol
+ *
+ * Requested by Martin Vidner <martin at vidner.net>.
+ */
+#define DLT_DBUS 231
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes at juniper.net>.
+ */
+#define DLT_JUNIPER_VS 232
+#define DLT_JUNIPER_SRX_E2E 233
+#define DLT_JUNIPER_FIBRECHANNEL 234
+
+/*
+ * DVB-CI (DVB Common Interface for communication between a PC Card
+ * module and a DVB receiver). See
+ *
+ * http://www.kaiser.cx/pcap-dvbci.html
+ *
+ * for the specification.
+ *
+ * Requested by Martin Kaiser <martin at kaiser.cx>.
+ */
+#define DLT_DVB_CI 235
+
+/*
+ * Variant of 3GPP TS 27.010 multiplexing protocol (similar to, but
+ * *not* the same as, 27.010). Requested by Hans-Christoph Schemmel
+ * <hans-christoph.schemmel at cinterion.com>.
+ */
+#define DLT_MUX27010 236
+
+/*
+ * STANAG 5066 D_PDUs. Requested by M. Baris Demiray
+ * <barisdemiray at gmail.com>.
+ */
+#define DLT_STANAG_5066_D_PDU 237
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes at juniper.net>.
+ */
+#define DLT_JUNIPER_ATM_CEMIC 238
+
+/*
+ * NetFilter LOG messages
+ * (payload of netlink NFNL_SUBSYS_ULOG/NFULNL_MSG_PACKET packets)
+ *
+ * Requested by Jakub Zawadzki <darkjames-ws at darkjames.pl>
+ */
+#define DLT_NFLOG 239
+
+/*
+ * Hilscher Gesellschaft fuer Systemautomation mbH link-layer type
+ * for Ethernet packets with a 4-byte pseudo-header and always
+ * with the payload including the FCS, as supplied by their
+ * netANALYZER hardware and software.
+ *
+ * Requested by Holger P. Frommer <HPfrommer at hilscher.com>
+ */
+#define DLT_NETANALYZER 240
+
+/*
+ * Hilscher Gesellschaft fuer Systemautomation mbH link-layer type
+ * for Ethernet packets with a 4-byte pseudo-header and FCS and
+ * with the Ethernet header preceded by 7 bytes of preamble and
+ * 1 byte of SFD, as supplied by their netANALYZER hardware and
+ * software.
+ *
+ * Requested by Holger P. Frommer <HPfrommer at hilscher.com>
+ */
+#define DLT_NETANALYZER_TRANSPARENT 241
+
+/*
+ * IP-over-Infiniband, as specified by RFC 4391.
+ *
+ * Requested by Petr Sumbera <petr.sumbera at oracle.com>.
+ */
+#define DLT_IPOIB 242
+
+#define DLT_MATCHING_MAX 242 /* highest value in the "matching" range */
/*
* DLT and savefile link type values are split into a class and
@@ -1105,6 +1225,7 @@
struct ifnet *bif_ifp; /* corresponding interface */
struct rwlock bif_lock; /* interface lock */
LIST_HEAD(, bpf_d) bif_wlist; /* writer-only list */
+ int flags; /* Interface flags */
#endif
};
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/net/bpf_buffer.c
--- a/head/sys/net/bpf_buffer.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/net/bpf_buffer.c Wed Jul 25 16:47:10 2012 +0300
@@ -62,7 +62,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/net/bpf_buffer.c 233937 2012-04-06 06:53:58Z melifaro $");
+__FBSDID("$FreeBSD: head/sys/net/bpf_buffer.c 235746 2012-05-21 22:19:19Z melifaro $");
#include "opt_bpf.h"
@@ -93,21 +93,6 @@
SYSCTL_INT(_net_bpf, OID_AUTO, maxbufsize, CTLFLAG_RW,
&bpf_maxbufsize, 0, "Maximum capture buffer in bytes");
-void
-bpf_buffer_alloc(struct bpf_d *d)
-{
-
- KASSERT(d->bd_fbuf == NULL, ("bpf_buffer_alloc: bd_fbuf != NULL"));
- KASSERT(d->bd_sbuf == NULL, ("bpf_buffer_alloc: bd_sbuf != NULL"));
- KASSERT(d->bd_hbuf == NULL, ("bpf_buffer_alloc: bd_hbuf != NULL"));
-
- d->bd_fbuf = (caddr_t)malloc(d->bd_bufsize, M_BPF, M_WAITOK);
- d->bd_sbuf = (caddr_t)malloc(d->bd_bufsize, M_BPF, M_WAITOK);
- d->bd_hbuf = NULL;
- d->bd_slen = 0;
- d->bd_hlen = 0;
-}
-
/*
* Simple data copy to the current kernel buffer.
*/
@@ -183,19 +168,43 @@
bpf_buffer_ioctl_sblen(struct bpf_d *d, u_int *i)
{
u_int size;
+ caddr_t fbuf, sbuf;
- BPFD_WLOCK(d);
- if (d->bd_bif != NULL) {
- BPFD_WUNLOCK(d);
- return (EINVAL);
- }
size = *i;
if (size > bpf_maxbufsize)
*i = size = bpf_maxbufsize;
else if (size < BPF_MINBUFSIZE)
*i = size = BPF_MINBUFSIZE;
+
+ /* Allocate buffers immediately */
+ fbuf = (caddr_t)malloc(size, M_BPF, M_WAITOK);
+ sbuf = (caddr_t)malloc(size, M_BPF, M_WAITOK);
+
+ BPFD_LOCK(d);
+ if (d->bd_bif != NULL) {
+ /* Interface already attached, unable to change buffers */
+ BPFD_UNLOCK(d);
+ free(fbuf, M_BPF);
+ free(sbuf, M_BPF);
+ return (EINVAL);
+ }
+
+ /* Free old buffers if set */
+ if (d->bd_fbuf != NULL)
+ free(d->bd_fbuf, M_BPF);
+ if (d->bd_sbuf != NULL)
+ free(d->bd_sbuf, M_BPF);
+
+ /* Fill in new data */
d->bd_bufsize = size;
- BPFD_WUNLOCK(d);
+ d->bd_fbuf = fbuf;
+ d->bd_sbuf = sbuf;
+
+ d->bd_hbuf = NULL;
+ d->bd_slen = 0;
+ d->bd_hlen = 0;
+
+ BPFD_UNLOCK(d);
return (0);
}
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/net/bpf_buffer.h
--- a/head/sys/net/bpf_buffer.h Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/net/bpf_buffer.h Wed Jul 25 16:47:10 2012 +0300
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: head/sys/net/bpf_buffer.h 230108 2012-01-14 17:07:52Z eadler $
+ * $FreeBSD: head/sys/net/bpf_buffer.h 235746 2012-05-21 22:19:19Z melifaro $
*/
#ifndef _NET_BPF_BUFFER_H_
@@ -36,7 +36,6 @@
#error "no user-serviceable parts inside"
#endif
-void bpf_buffer_alloc(struct bpf_d *d);
void bpf_buffer_append_bytes(struct bpf_d *d, caddr_t buf, u_int offset,
void *src, u_int len);
void bpf_buffer_append_mbuf(struct bpf_d *d, caddr_t buf, u_int offset,
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/net/bpf_zerocopy.c
--- a/head/sys/net/bpf_zerocopy.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/net/bpf_zerocopy.c Wed Jul 25 16:47:10 2012 +0300
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/net/bpf_zerocopy.c 233937 2012-04-06 06:53:58Z melifaro $");
+__FBSDID("$FreeBSD: head/sys/net/bpf_zerocopy.c 235745 2012-05-21 22:17:29Z melifaro $");
#include "opt_bpf.h"
@@ -515,14 +515,14 @@
struct zbuf *bzh;
bzero(bz, sizeof(*bz));
- BPFD_WLOCK(d);
+ BPFD_LOCK(d);
if (d->bd_hbuf == NULL && d->bd_slen != 0) {
ROTATE_BUFFERS(d);
bzh = (struct zbuf *)d->bd_hbuf;
bz->bz_bufa = (void *)bzh->zb_uaddr;
bz->bz_buflen = d->bd_hlen;
}
- BPFD_WUNLOCK(d);
+ BPFD_UNLOCK(d);
return (0);
}
@@ -570,10 +570,10 @@
* We only allow buffers to be installed once, so atomically check
* that no buffers are currently installed and install new buffers.
*/
- BPFD_WLOCK(d);
+ BPFD_LOCK(d);
if (d->bd_hbuf != NULL || d->bd_sbuf != NULL || d->bd_fbuf != NULL ||
d->bd_bif != NULL) {
- BPFD_WUNLOCK(d);
+ BPFD_UNLOCK(d);
zbuf_free(zba);
zbuf_free(zbb);
return (EINVAL);
@@ -593,6 +593,6 @@
* shared management region.
*/
d->bd_bufsize = bz->bz_buflen - sizeof(struct bpf_zbuf_header);
- BPFD_WUNLOCK(d);
+ BPFD_UNLOCK(d);
return (0);
}
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/net/bpfdesc.h
--- a/head/sys/net/bpfdesc.h Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/net/bpfdesc.h Wed Jul 25 16:47:10 2012 +0300
@@ -33,7 +33,7 @@
*
* @(#)bpfdesc.h 8.1 (Berkeley) 6/10/93
*
- * $FreeBSD: head/sys/net/bpfdesc.h 233938 2012-04-06 06:55:21Z melifaro $
+ * $FreeBSD: head/sys/net/bpfdesc.h 235745 2012-05-21 22:17:29Z melifaro $
*/
#ifndef _NET_BPFDESC_H_
@@ -88,7 +88,7 @@
int bd_sig; /* signal to send upon packet reception */
struct sigio * bd_sigio; /* information for async I/O */
struct selinfo bd_sel; /* bsd select info */
- struct rwlock bd_lock; /* per-descriptor lock */
+ struct mtx bd_lock; /* per-descriptor lock */
struct callout bd_callout; /* for BPF timeouts with select */
struct label *bd_label; /* MAC label for descriptor */
u_int64_t bd_fcount; /* number of packets which matched filter */
@@ -107,12 +107,9 @@
#define BPF_WAITING 1 /* waiting for read timeout in select */
#define BPF_TIMED_OUT 2 /* read timeout has expired in select */
-#define BPFD_RLOCK(bd) rw_rlock(&(bd)->bd_lock)
-#define BPFD_RUNLOCK(bd) rw_runlock(&(bd)->bd_lock)
-#define BPFD_WLOCK(bd) rw_wlock(&(bd)->bd_lock)
-#define BPFD_WUNLOCK(bd) rw_wunlock(&(bd)->bd_lock)
-#define BPFD_WLOCK_ASSERT(bd) rw_assert(&(bd)->bd_lock, RA_WLOCKED)
-#define BPFD_LOCK_ASSERT(bd) rw_assert(&(bd)->bd_lock, RA_LOCKED)
+#define BPFD_LOCK(bd) mtx_lock(&(bd)->bd_lock)
+#define BPFD_UNLOCK(bd) mtx_unlock(&(bd)->bd_lock)
+#define BPFD_LOCK_ASSERT(bd) mtx_assert(&(bd)->bd_lock, MA_OWNED)
#define BPF_PID_REFRESH(bd, td) (bd)->bd_pid = (td)->td_proc->p_pid
#define BPF_PID_REFRESH_CUR(bd) (bd)->bd_pid = curthread->td_proc->p_pid
@@ -159,4 +156,6 @@
#define BPFIF_WLOCK(bif) rw_wlock(&(bif)->bif_lock)
#define BPFIF_WUNLOCK(bif) rw_wunlock(&(bif)->bif_lock)
+#define BPFIF_FLAG_DYING 1 /* Reject new bpf consumers */
+
#endif
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/net/flowtable.c
--- a/head/sys/net/flowtable.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/net/flowtable.c Wed Jul 25 16:47:10 2012 +0300
@@ -34,7 +34,7 @@
#include "opt_inet6.h"
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/net/flowtable.c 231852 2012-02-17 02:39:58Z bz $");
+__FBSDID("$FreeBSD: head/sys/net/flowtable.c 238092 2012-07-04 07:37:53Z glebius $");
#include <sys/param.h>
#include <sys/types.h>
@@ -619,6 +619,7 @@
sin->sin_addr.s_addr = hashkey[2];
ro->ro_rt = __DEVOLATILE(struct rtentry *, fle->f_rt);
ro->ro_lle = __DEVOLATILE(struct llentry *, fle->f_lle);
+ ro->ro_flags |= RT_NORTREF;
}
#endif /* INET */
@@ -826,7 +827,7 @@
memcpy(&sin6->sin6_addr, &hashkey[5], sizeof (struct in6_addr));
ro->ro_rt = __DEVOLATILE(struct rtentry *, fle->f_rt);
ro->ro_lle = __DEVOLATILE(struct llentry *, fle->f_lle);
-
+ ro->ro_flags |= RT_NORTREF;
}
#endif /* INET6 */
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/net/ieee8023ad_lacp.c
--- a/head/sys/net/ieee8023ad_lacp.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/net/ieee8023ad_lacp.c Wed Jul 25 16:47:10 2012 +0300
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/net/ieee8023ad_lacp.c 232629 2012-03-06 22:58:13Z thompsa $");
+__FBSDID("$FreeBSD: head/sys/net/ieee8023ad_lacp.c 236062 2012-05-26 08:09:01Z thompsa $");
#include <sys/param.h>
#include <sys/callout.h>
@@ -38,6 +38,7 @@
#include <sys/kernel.h> /* hz */
#include <sys/socket.h> /* for net/if.h */
#include <sys/sockio.h>
+#include <sys/sysctl.h>
#include <machine/stdarg.h>
#include <sys/lock.h>
#include <sys/rwlock.h>
@@ -168,7 +169,8 @@
static int lacp_xmit_lacpdu(struct lacp_port *);
static int lacp_xmit_marker(struct lacp_port *);
-#if defined(LACP_DEBUG)
+/* Debugging */
+
static void lacp_dump_lacpdu(const struct lacpdu *);
static const char *lacp_format_partner(const struct lacp_peerinfo *, char *,
size_t);
@@ -184,10 +186,14 @@
size_t);
static void lacp_dprintf(const struct lacp_port *, const char *, ...)
__attribute__((__format__(__printf__, 2, 3)));
-#define LACP_DPRINTF(a) lacp_dprintf a
-#else
-#define LACP_DPRINTF(a) /* nothing */
-#endif
+
+static int lacp_debug = 0;
+SYSCTL_INT(_net, OID_AUTO, lacp_debug, CTLFLAG_RW | CTLFLAG_TUN,
+ &lacp_debug, 0, "Enable LACP debug logging (1=debug, 2=trace)");
+TUNABLE_INT("net.lacp_debug", &lacp_debug);
+
+#define LACP_DPRINTF(a) if (lacp_debug > 0) { lacp_dprintf a ; }
+#define LACP_TRACE(a) if (lacp_debug > 1) { lacp_dprintf(a,"%s\n",__func__); }
/*
* partner administration variables.
@@ -290,10 +296,10 @@
goto bad;
}
-#if defined(LACP_DEBUG)
- LACP_DPRINTF((lp, "lacpdu receive\n"));
- lacp_dump_lacpdu(du);
-#endif /* defined(LACP_DEBUG) */
+ if (lacp_debug > 0) {
+ lacp_dprintf(lp, "lacpdu receive\n");
+ lacp_dump_lacpdu(du);
+ }
LACP_LOCK(lsc);
lacp_sm_rx(lp, du);
@@ -370,10 +376,10 @@
sizeof(du->ldu_collector));
du->ldu_collector.lci_maxdelay = 0;
-#if defined(LACP_DEBUG)
- LACP_DPRINTF((lp, "lacpdu transmit\n"));
- lacp_dump_lacpdu(du);
-#endif /* defined(LACP_DEBUG) */
+ if (lacp_debug > 0) {
+ lacp_dprintf(lp, "lacpdu transmit\n");
+ lacp_dump_lacpdu(du);
+ }
m->m_flags |= M_MCAST;
@@ -647,9 +653,7 @@
{
struct lacp_aggregator *la = lp->lp_aggregator;
struct lacp_softc *lsc = lp->lp_lsc;
-#if defined(LACP_DEBUG)
char buf[LACP_LAGIDSTR_MAX+1];
-#endif /* defined(LACP_DEBUG) */
LACP_LOCK_ASSERT(lsc);
@@ -684,9 +688,7 @@
{
struct lacp_aggregator *la = lp->lp_aggregator;
struct lacp_softc *lsc = lp->lp_lsc;
-#if defined(LACP_DEBUG)
char buf[LACP_LAGIDSTR_MAX+1];
-#endif /* defined(LACP_DEBUG) */
LACP_LOCK_ASSERT(lsc);
@@ -720,7 +722,8 @@
LACP_LOCK_ASSERT(lsc);
- LACP_DPRINTF((NULL, "%s\n", __func__));
+ LACP_TRACE(NULL);
+
lsc->lsc_suppress_distributing = FALSE;
}
@@ -838,7 +841,8 @@
return;
}
- LACP_DPRINTF((NULL, "%s\n", __func__));
+ LACP_TRACE(NULL);
+
lsc->lsc_suppress_distributing = TRUE;
/* send a marker frame down each port to verify the queues are empty */
@@ -908,11 +912,9 @@
struct lacp_aggregator *la;
struct lacp_aggregator *best_la = NULL;
uint64_t best_speed = 0;
-#if defined(LACP_DEBUG)
char buf[LACP_LAGIDSTR_MAX+1];
-#endif /* defined(LACP_DEBUG) */
- LACP_DPRINTF((NULL, "%s:\n", __func__));
+ LACP_TRACE(NULL);
TAILQ_FOREACH(la, &lsc->lsc_aggregators, la_q) {
uint64_t speed;
@@ -946,7 +948,6 @@
KASSERT(best_la == NULL || !TAILQ_EMPTY(&best_la->la_ports),
("invalid aggregator list"));
-#if defined(LACP_DEBUG)
if (lsc->lsc_active_aggregator != best_la) {
LACP_DPRINTF((NULL, "active aggregator changed\n"));
LACP_DPRINTF((NULL, "old %s\n",
@@ -957,7 +958,6 @@
}
LACP_DPRINTF((NULL, "new %s\n",
lacp_format_lagid_aggregator(best_la, buf, sizeof(buf))));
-#endif /* defined(LACP_DEBUG) */
if (lsc->lsc_active_aggregator != best_la) {
sc->sc_ifp->if_baudrate = best_speed;
@@ -1040,9 +1040,7 @@
static void
lacp_aggregator_addref(struct lacp_softc *lsc, struct lacp_aggregator *la)
{
-#if defined(LACP_DEBUG)
char buf[LACP_LAGIDSTR_MAX+1];
-#endif
LACP_DPRINTF((NULL, "%s: lagid=%s, refcnt %d -> %d\n",
__func__,
@@ -1058,9 +1056,7 @@
static void
lacp_aggregator_delref(struct lacp_softc *lsc, struct lacp_aggregator *la)
{
-#if defined(LACP_DEBUG)
char buf[LACP_LAGIDSTR_MAX+1];
-#endif
LACP_DPRINTF((NULL, "%s: lagid=%s, refcnt %d -> %d\n",
__func__,
@@ -1195,9 +1191,7 @@
{
struct lacp_softc *lsc = lp->lp_lsc;
struct lacp_aggregator *la;
-#if defined(LACP_DEBUG)
char buf[LACP_LAGIDSTR_MAX+1];
-#endif
if (lp->lp_aggregator) {
return;
@@ -1278,7 +1272,8 @@
enum lacp_selected selected = lp->lp_selected;
struct lacp_aggregator *la;
- /* LACP_DPRINTF((lp, "%s: state %d\n", __func__, lp->lp_mux_state)); */
+ if (lacp_debug > 1)
+ lacp_dprintf(lp, "%s: state %d\n", __func__, lp->lp_mux_state);
re_eval:
la = lp->lp_aggregator;
@@ -1387,9 +1382,7 @@
lacp_sm_mux_timer(struct lacp_port *lp)
{
struct lacp_aggregator *la = lp->lp_aggregator;
-#if defined(LACP_DEBUG)
char buf[LACP_LAGIDSTR_MAX+1];
-#endif
KASSERT(la->la_pending > 0, ("no pending event"));
@@ -1537,11 +1530,9 @@
{
boolean_t active;
uint8_t oldpstate;
-#if defined(LACP_DEBUG)
char buf[LACP_STATESTR_MAX+1];
-#endif
- /* LACP_DPRINTF((lp, "%s\n", __func__)); */
+ LACP_TRACE(lp);
oldpstate = lp->lp_partner.lip_state;
@@ -1576,7 +1567,8 @@
static void
lacp_sm_rx_update_ntt(struct lacp_port *lp, const struct lacpdu *du)
{
- /* LACP_DPRINTF((lp, "%s\n", __func__)); */
+
+ LACP_TRACE(lp);
if (lacp_compare_peerinfo(&lp->lp_actor, &du->ldu_partner) ||
!LACP_STATE_EQ(lp->lp_state, du->ldu_partner.lip_state,
@@ -1591,7 +1583,7 @@
{
uint8_t oldpstate;
- /* LACP_DPRINTF((lp, "%s\n", __func__)); */
+ LACP_TRACE(lp);
oldpstate = lp->lp_partner.lip_state;
lp->lp_partner = lacp_partner_admin;
@@ -1603,7 +1595,8 @@
lacp_sm_rx_update_selected_from_peerinfo(struct lacp_port *lp,
const struct lacp_peerinfo *info)
{
- /* LACP_DPRINTF((lp, "%s\n", __func__)); */
+
+ LACP_TRACE(lp);
if (lacp_compare_peerinfo(&lp->lp_partner, info) ||
!LACP_STATE_EQ(lp->lp_partner.lip_state, info->lip_state,
@@ -1616,7 +1609,8 @@
static void
lacp_sm_rx_update_selected(struct lacp_port *lp, const struct lacpdu *du)
{
- /* LACP_DPRINTF((lp, "%s\n", __func__)); */
+
+ LACP_TRACE(lp);
lacp_sm_rx_update_selected_from_peerinfo(lp, &du->ldu_actor);
}
@@ -1624,7 +1618,8 @@
static void
lacp_sm_rx_update_default_selected(struct lacp_port *lp)
{
- /* LACP_DPRINTF((lp, "%s\n", __func__)); */
+
+ LACP_TRACE(lp);
lacp_sm_rx_update_selected_from_peerinfo(lp, &lacp_partner_admin);
}
@@ -1812,7 +1807,7 @@
return (0);
}
-#if defined(LACP_DEBUG)
+/* Debugging */
const char *
lacp_format_mac(const uint8_t *mac, char *buf, size_t buflen)
{
@@ -1942,4 +1937,3 @@
vprintf(fmt, va);
va_end(va);
}
-#endif
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/net/if.h
--- a/head/sys/net/if.h Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/net/if.h Wed Jul 25 16:47:10 2012 +0300
@@ -27,7 +27,7 @@
* SUCH DAMAGE.
*
* @(#)if.h 8.1 (Berkeley) 6/10/93
- * $FreeBSD: head/sys/net/if.h 231505 2012-02-11 06:02:16Z bz $
+ * $FreeBSD: head/sys/net/if.h 237787 2012-06-29 15:21:34Z jhb $
*/
#ifndef _NET_IF_H_
@@ -153,7 +153,6 @@
#define IFF_STATICARP 0x80000 /* (n) static ARP */
#define IFF_DYING 0x200000 /* (n) interface is winding down */
#define IFF_RENAMING 0x400000 /* (n) interface is being renamed */
-
/*
* Old names for driver flags so that user space tools can continue to use
* the old (portable) names.
@@ -230,6 +229,10 @@
#define IFCAP_VLAN_HWTSO 0x40000 /* can do IFCAP_TSO on VLANs */
#define IFCAP_LINKSTATE 0x80000 /* the runtime link state is dynamic */
#define IFCAP_NETMAP 0x100000 /* netmap mode supported/enabled */
+#define IFCAP_RXCSUM_IPV6 0x200000 /* can offload checksum on IPv6 RX */
+#define IFCAP_TXCSUM_IPV6 0x400000 /* can offload checksum on IPv6 TX */
+
+#define IFCAP_HWCSUM_IPV6 (IFCAP_RXCSUM_IPV6 | IFCAP_TXCSUM_IPV6)
#define IFCAP_HWCSUM (IFCAP_RXCSUM | IFCAP_TXCSUM)
#define IFCAP_TSO (IFCAP_TSO4 | IFCAP_TSO6)
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/net/if_bridge.c
--- a/head/sys/net/if_bridge.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/net/if_bridge.c Wed Jul 25 16:47:10 2012 +0300
@@ -75,7 +75,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/net/if_bridge.c 234487 2012-04-20 09:55:50Z thompsa $");
+__FBSDID("$FreeBSD: head/sys/net/if_bridge.c 238355 2012-07-10 20:59:35Z emaste $");
#include "opt_inet.h"
#include "opt_inet6.h"
@@ -334,6 +334,7 @@
static int bridge_fragment(struct ifnet *, struct mbuf *,
struct ether_header *, int, struct llc *);
static void bridge_linkstate(struct ifnet *ifp);
+static void bridge_linkcheck(struct bridge_softc *sc);
extern void (*bridge_linkstate_p)(struct ifnet *ifp);
@@ -964,6 +965,7 @@
EVENTHANDLER_INVOKE(iflladdr_event, sc->sc_ifp);
}
+ bridge_linkcheck(sc);
bridge_mutecaps(sc); /* recalcuate now this interface is removed */
bridge_rtdelete(sc, ifs, IFBF_FLUSHALL);
KASSERT(bif->bif_addrcnt == 0,
@@ -993,7 +995,6 @@
bridge_set_ifcap(sc, bif, bif->bif_savedcaps);
}
bstp_destroy(&bif->bif_stp); /* prepare to free */
- bridge_linkstate(ifs);
BRIDGE_LOCK(sc);
free(bif, M_DEVBUF);
}
@@ -1092,18 +1093,17 @@
/* Set interface capabilities to the intersection set of all members */
bridge_mutecaps(sc);
-
- BRIDGE_UNLOCK(sc);
- /* Update the linkstate for the bridge */
- bridge_linkstate(ifs);
+ bridge_linkcheck(sc);
+
/* Place the interface into promiscuous mode */
switch (ifs->if_type) {
case IFT_ETHER:
case IFT_L2VLAN:
+ BRIDGE_UNLOCK(sc);
error = ifpromisc(ifs, 1);
+ BRIDGE_LOCK(sc);
break;
}
- BRIDGE_LOCK(sc);
if (error)
bridge_delete_member(sc, bif, 0);
out:
@@ -1811,8 +1811,10 @@
m->m_flags &= ~M_VLANTAG;
}
- if (err == 0)
- dst_ifp->if_transmit(dst_ifp, m);
+ if ((err = dst_ifp->if_transmit(dst_ifp, m))) {
+ m_freem(m0);
+ break;
+ }
}
if (err == 0) {
@@ -3486,8 +3488,7 @@
bridge_linkstate(struct ifnet *ifp)
{
struct bridge_softc *sc = ifp->if_bridge;
- struct bridge_iflist *bif, *bif2;
- int new_link, hasls;
+ struct bridge_iflist *bif;
BRIDGE_LOCK(sc);
bif = bridge_lookup_member_if(sc, ifp);
@@ -3495,13 +3496,26 @@
BRIDGE_UNLOCK(sc);
return;
}
+ bridge_linkcheck(sc);
+ BRIDGE_UNLOCK(sc);
+
+ bstp_linkstate(&bif->bif_stp);
+}
+
+static void
+bridge_linkcheck(struct bridge_softc *sc)
+{
+ struct bridge_iflist *bif;
+ int new_link, hasls;
+
+ BRIDGE_LOCK_ASSERT(sc);
new_link = LINK_STATE_DOWN;
hasls = 0;
/* Our link is considered up if at least one of our ports is active */
- LIST_FOREACH(bif2, &sc->sc_iflist, bif_next) {
- if (bif2->bif_ifp->if_capabilities & IFCAP_LINKSTATE)
+ LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
+ if (bif->bif_ifp->if_capabilities & IFCAP_LINKSTATE)
hasls++;
- if (bif2->bif_ifp->if_link_state == LINK_STATE_UP) {
+ if (bif->bif_ifp->if_link_state == LINK_STATE_UP) {
new_link = LINK_STATE_UP;
break;
}
@@ -3511,8 +3525,4 @@
new_link = LINK_STATE_UP;
}
if_link_state_change(sc->sc_ifp, new_link);
- BRIDGE_UNLOCK(sc);
-
- bstp_linkstate(&bif->bif_stp);
}
-
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/net/if_dl.h
--- a/head/sys/net/if_dl.h Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/net/if_dl.h Wed Jul 25 16:47:10 2012 +0300
@@ -27,7 +27,7 @@
* SUCH DAMAGE.
*
* @(#)if_dl.h 8.1 (Berkeley) 6/10/93
- * $FreeBSD$
+ * $FreeBSD: head/sys/net/if_dl.h 235640 2012-05-19 02:39:43Z marcel $
*/
#ifndef _NET_IF_DL_H_
@@ -67,6 +67,7 @@
};
#define LLADDR(s) ((caddr_t)((s)->sdl_data + (s)->sdl_nlen))
+#define LLINDEX(s) ((s)->sdl_index)
#ifndef _KERNEL
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/net/if_epair.c
--- a/head/sys/net/if_epair.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/net/if_epair.c Wed Jul 25 16:47:10 2012 +0300
@@ -48,7 +48,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/net/if_epair.c 227309 2011-11-07 15:43:11Z ed $");
+__FBSDID("$FreeBSD: head/sys/net/if_epair.c 238309 2012-07-09 20:38:18Z trociny $");
#include <sys/param.h>
#include <sys/kernel.h>
@@ -904,39 +904,41 @@
if_link_state_change(oifp, LINK_STATE_DOWN);
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
oifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+
+ /*
+ * Get rid of our second half. As the other of the two
+ * interfaces may reside in a different vnet, we need to
+ * switch before freeing them.
+ */
+ CURVNET_SET_QUIET(oifp->if_vnet);
ether_ifdetach(oifp);
- ether_ifdetach(ifp);
/*
* Wait for all packets to be dispatched to if_input.
- * The numbers can only go down as the interfaces are
+ * The numbers can only go down as the interface is
* detached so there is no need to use atomics.
*/
- DPRINTF("sca refcnt=%u scb refcnt=%u\n", sca->refcount, scb->refcount);
- EPAIR_REFCOUNT_ASSERT(sca->refcount == 1 && scb->refcount == 1,
- ("%s: ifp=%p sca->refcount!=1: %d || ifp=%p scb->refcount!=1: %d",
- __func__, ifp, sca->refcount, oifp, scb->refcount));
-
- /*
- * Get rid of our second half.
- */
+ DPRINTF("scb refcnt=%u\n", scb->refcount);
+ EPAIR_REFCOUNT_ASSERT(scb->refcount == 1,
+ ("%s: ifp=%p scb->refcount!=1: %d", __func__, oifp, scb->refcount));
oifp->if_softc = NULL;
error = if_clone_destroyif(ifc, oifp);
if (error)
panic("%s: if_clone_destroyif() for our 2nd iface failed: %d",
__func__, error);
+ if_free(oifp);
+ ifmedia_removeall(&scb->media);
+ free(scb, M_EPAIR);
+ CURVNET_RESTORE();
+ ether_ifdetach(ifp);
/*
- * Finish cleaning up. Free them and release the unit.
- * As the other of the two interfaces my reside in a different vnet,
- * we need to switch before freeing them.
+ * Wait for all packets to be dispatched to if_input.
*/
- CURVNET_SET_QUIET(oifp->if_vnet);
- if_free(oifp);
- CURVNET_RESTORE();
+ DPRINTF("sca refcnt=%u\n", sca->refcount);
+ EPAIR_REFCOUNT_ASSERT(sca->refcount == 1,
+ ("%s: ifp=%p sca->refcount!=1: %d", __func__, ifp, sca->refcount));
if_free(ifp);
ifmedia_removeall(&sca->media);
- ifmedia_removeall(&scb->media);
- free(scb, M_EPAIR);
free(sca, M_EPAIR);
ifc_free_unit(ifc, unit);
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/net/if_ethersubr.c
--- a/head/sys/net/if_ethersubr.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/net/if_ethersubr.c Wed Jul 25 16:47:10 2012 +0300
@@ -27,7 +27,7 @@
* SUCH DAMAGE.
*
* @(#)if_ethersubr.c 8.1 (Berkeley) 6/10/93
- * $FreeBSD: head/sys/net/if_ethersubr.c 232487 2012-03-04 11:11:03Z zec $
+ * $FreeBSD: head/sys/net/if_ethersubr.c 234946 2012-05-03 08:56:43Z melifaro $
*/
#include "opt_atalk.h"
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/net/if_gif.c
--- a/head/sys/net/if_gif.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/net/if_gif.c Wed Jul 25 16:47:10 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/sys/net/if_gif.c 227309 2011-11-07 15:43:11Z ed $ */
+/* $FreeBSD: head/sys/net/if_gif.c 237787 2012-06-29 15:21:34Z jhb $ */
/* $KAME: if_gif.c,v 1.87 2001/10/19 08:50:27 itojun Exp $ */
/*-
@@ -342,26 +342,82 @@
return 0;
}
}
+#ifdef INET
+#define GIF_HDR_LEN (ETHER_HDR_LEN + sizeof (struct ip))
+#endif
+#ifdef INET6
+#define GIF_HDR_LEN6 (ETHER_HDR_LEN + sizeof (struct ip6_hdr))
+#endif
static void
gif_start(struct ifnet *ifp)
{
struct gif_softc *sc;
struct mbuf *m;
+ uint32_t af;
+ int error = 0;
sc = ifp->if_softc;
+ GIF_LOCK(sc);
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) {
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
- for (;;) {
- IFQ_DEQUEUE(&ifp->if_snd, m);
+ IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
if (m == 0)
break;
- gif_output(ifp, m, sc->gif_pdst, NULL);
+#ifdef ALTQ
+ /* Take out those altq bytes we add in gif_output */
+#ifdef INET
+ if (sc->gif_psrc->sa_family == AF_INET)
+ m->m_pkthdr.len -= GIF_HDR_LEN;
+#endif
+#ifdef INET6
+ if (sc->gif_psrc->sa_family == AF_INET6)
+ m->m_pkthdr.len -= GIF_HDR_LEN6;
+#endif
+#endif
+ /*
+ * Now pull back the af that we
+ * stashed in the csum_data.
+ */
+ af = m->m_pkthdr.csum_data;
+
+ if (ifp->if_bridge)
+ af = AF_LINK;
+
+ BPF_MTAP2(ifp, &af, sizeof(af), m);
+ ifp->if_opackets++;
+
+/* Done by IFQ_HANDOFF */
+/* ifp->if_obytes += m->m_pkthdr.len;*/
+ /* override to IPPROTO_ETHERIP for bridged traffic */
+
+ M_SETFIB(m, sc->gif_fibnum);
+ /* inner AF-specific encapsulation */
+ /* XXX should we check if our outer source is legal? */
+ /* dispatch to output logic based on outer AF */
+ switch (sc->gif_psrc->sa_family) {
+#ifdef INET
+ case AF_INET:
+ error = in_gif_output(ifp, af, m);
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ error = in6_gif_output(ifp, af, m);
+ break;
+#endif
+ default:
+ m_freem(m);
+ error = ENETDOWN;
+ }
+ if (error)
+ ifp->if_oerrors++;
}
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
-
+ GIF_UNLOCK(sc);
return;
}
@@ -376,8 +432,7 @@
struct m_tag *mtag;
int error = 0;
int gif_called;
- u_int32_t af;
-
+ uint32_t af;
#ifdef MAC
error = mac_ifnet_check_transmit(ifp, m);
if (error) {
@@ -426,55 +481,45 @@
m_tag_prepend(m, mtag);
m->m_flags &= ~(M_BCAST|M_MCAST);
-
- GIF_LOCK(sc);
-
- if (!(ifp->if_flags & IFF_UP) ||
- sc->gif_psrc == NULL || sc->gif_pdst == NULL) {
- GIF_UNLOCK(sc);
- m_freem(m);
- error = ENETDOWN;
- goto end;
- }
-
/* BPF writes need to be handled specially. */
if (dst->sa_family == AF_UNSPEC) {
bcopy(dst->sa_data, &af, sizeof(af));
dst->sa_family = af;
}
-
af = dst->sa_family;
- BPF_MTAP2(ifp, &af, sizeof(af), m);
- ifp->if_opackets++;
- ifp->if_obytes += m->m_pkthdr.len;
-
- /* override to IPPROTO_ETHERIP for bridged traffic */
- if (ifp->if_bridge)
- af = AF_LINK;
-
- M_SETFIB(m, sc->gif_fibnum);
- /* inner AF-specific encapsulation */
-
- /* XXX should we check if our outer source is legal? */
-
- /* dispatch to output logic based on outer AF */
- switch (sc->gif_psrc->sa_family) {
+ /*
+ * Now save the af in the inbound pkt csum
+ * data, this is a cheat since we are using
+ * the inbound csum_data field to carry the
+ * af over to the gif_start() routine, avoiding
+ * using yet another mtag.
+ */
+ m->m_pkthdr.csum_data = af;
+ if (!(ifp->if_flags & IFF_UP) ||
+ sc->gif_psrc == NULL || sc->gif_pdst == NULL) {
+ m_freem(m);
+ error = ENETDOWN;
+ goto end;
+ }
+#ifdef ALTQ
+ /*
+ * Make altq aware of the bytes we will add
+ * when we actually send it.
+ */
#ifdef INET
- case AF_INET:
- error = in_gif_output(ifp, af, m);
- break;
+ if (sc->gif_psrc->sa_family == AF_INET)
+ m->m_pkthdr.len += GIF_HDR_LEN;
#endif
#ifdef INET6
- case AF_INET6:
- error = in6_gif_output(ifp, af, m);
- break;
+ if (sc->gif_psrc->sa_family == AF_INET6)
+ m->m_pkthdr.len += GIF_HDR_LEN6;
#endif
- default:
- m_freem(m);
- error = ENETDOWN;
- }
-
- GIF_UNLOCK(sc);
+#endif
+ /*
+ * Queue message on interface, update output statistics if
+ * successful, and start output if interface not yet active.
+ */
+ IFQ_HANDOFF(ifp, m, error);
end:
if (error)
ifp->if_oerrors++;
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/net/if_lagg.c
--- a/head/sys/net/if_lagg.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/net/if_lagg.c Wed Jul 25 16:47:10 2012 +0300
@@ -18,7 +18,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/net/if_lagg.c 234163 2012-04-12 01:07:17Z thompsa $");
+__FBSDID("$FreeBSD: head/sys/net/if_lagg.c 237852 2012-06-30 19:09:02Z thompsa $");
#include "opt_inet.h"
#include "opt_inet6.h"
@@ -516,8 +516,13 @@
return (ENOSPC);
/* Check if port has already been associated to a lagg */
- if (ifp->if_lagg != NULL)
+ if (ifp->if_lagg != NULL) {
+ /* Port is already in the current lagg? */
+ lp = (struct lagg_port *)ifp->if_lagg;
+ if (lp->lp_softc == sc)
+ return (EEXIST);
return (EBUSY);
+ }
/* XXX Disallow non-ethernet interfaces (this should be any of 802) */
if (ifp->if_type != IFT_ETHER)
@@ -764,28 +769,18 @@
return (EINVAL);
}
+/*
+ * For direct output to child ports.
+ */
static int
lagg_port_output(struct ifnet *ifp, struct mbuf *m,
struct sockaddr *dst, struct route *ro)
{
struct lagg_port *lp = ifp->if_lagg;
- struct ether_header *eh;
- short type = 0;
switch (dst->sa_family) {
case pseudo_AF_HDRCMPLT:
case AF_UNSPEC:
- eh = (struct ether_header *)dst->sa_data;
- type = eh->ether_type;
- break;
- }
-
- /*
- * Only allow ethernet types required to initiate or maintain the link,
- * aggregated frames take a different path.
- */
- switch (ntohs(type)) {
- case ETHERTYPE_PAE: /* EAPOL PAE/802.1x */
return ((*lp->lp_output)(ifp, m, dst, ro));
}
@@ -802,6 +797,9 @@
if ((lp = ifp->if_lagg) == NULL)
return;
+ /* If the ifnet is just being renamed, don't do anything. */
+ if (ifp->if_flags & IFF_RENAMING)
+ return;
sc = lp->lp_softc;
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/net/if_loop.c
--- a/head/sys/net/if_loop.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/net/if_loop.c Wed Jul 25 16:47:10 2012 +0300
@@ -27,7 +27,7 @@
* SUCH DAMAGE.
*
* @(#)if_loop.c 8.2 (Berkeley) 1/9/95
- * $FreeBSD$
+ * $FreeBSD: head/sys/net/if_loop.c 236332 2012-05-30 20:56:07Z tuexen $
*/
/*
@@ -92,7 +92,9 @@
#endif
#define LO_CSUM_FEATURES (CSUM_IP | CSUM_TCP | CSUM_UDP | CSUM_SCTP)
-#define LO_CSUM_SET (CSUM_DATA_VALID | CSUM_PSEUDO_HDR | \
+#define LO_CSUM_FEATURES6 (CSUM_TCP_IPV6 | CSUM_UDP_IPV6 | CSUM_SCTP_IPV6)
+#define LO_CSUM_SET (CSUM_DATA_VALID | CSUM_DATA_VALID_IPV6 | \
+ CSUM_PSEUDO_HDR | \
CSUM_IP_CHECKED | CSUM_IP_VALID | \
CSUM_SCTP_VALID)
@@ -143,8 +145,9 @@
ifp->if_ioctl = loioctl;
ifp->if_output = looutput;
ifp->if_snd.ifq_maxlen = ifqmaxlen;
- ifp->if_capabilities = ifp->if_capenable = IFCAP_HWCSUM;
- ifp->if_hwassist = LO_CSUM_FEATURES;
+ ifp->if_capabilities = ifp->if_capenable =
+ IFCAP_HWCSUM | IFCAP_HWCSUM_IPV6;
+ ifp->if_hwassist = LO_CSUM_FEATURES | LO_CSUM_FEATURES6;
if_attach(ifp);
bpfattach(ifp, DLT_NULL, sizeof(u_int32_t));
if (V_loif == NULL)
@@ -252,7 +255,14 @@
m->m_pkthdr.csum_flags = LO_CSUM_SET;
}
m->m_pkthdr.csum_flags &= ~LO_CSUM_FEATURES;
+ break;
case AF_INET6:
+ if (ifp->if_capenable & IFCAP_RXCSUM_IPV6) {
+ m->m_pkthdr.csum_data = 0xffff;
+ m->m_pkthdr.csum_flags = LO_CSUM_SET;
+ }
+ m->m_pkthdr.csum_flags &= ~LO_CSUM_FEATURES6;
+ break;
case AF_IPX:
case AF_APPLETALK:
break;
@@ -436,10 +446,15 @@
ifp->if_capenable ^= IFCAP_RXCSUM;
if ((mask & IFCAP_TXCSUM) != 0)
ifp->if_capenable ^= IFCAP_TXCSUM;
+ if ((mask & IFCAP_RXCSUM_IPV6) != 0)
+ ifp->if_capenable ^= IFCAP_RXCSUM_IPV6;
+ if ((mask & IFCAP_TXCSUM_IPV6) != 0)
+ ifp->if_capenable ^= IFCAP_TXCSUM_IPV6;
+ ifp->if_hwassist = 0;
if (ifp->if_capenable & IFCAP_TXCSUM)
ifp->if_hwassist = LO_CSUM_FEATURES;
- else
- ifp->if_hwassist = 0;
+ if (ifp->if_capenable & IFCAP_TXCSUM_IPV6)
+ ifp->if_hwassist |= LO_CSUM_FEATURES6;
break;
default:
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/net/if_stf.c
--- a/head/sys/net/if_stf.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/net/if_stf.c Wed Jul 25 16:47:10 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/sys/net/if_stf.c 227309 2011-11-07 15:43:11Z ed $ */
+/* $FreeBSD: head/sys/net/if_stf.c 238492 2012-07-15 17:44:27Z melifaro $ */
/* $KAME: if_stf.c,v 1.73 2001/12/03 11:08:30 keiichi Exp $ */
/*-
@@ -793,7 +793,7 @@
struct rt_addrinfo *info;
{
RT_LOCK_ASSERT(rt);
- rt->rt_rmx.rmx_mtu = IPV6_MMTU;
+ rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu;
}
static int
@@ -806,7 +806,7 @@
struct ifreq *ifr;
struct sockaddr_in6 *sin6;
struct in_addr addr;
- int error;
+ int error, mtu;
error = 0;
switch (cmd) {
@@ -840,6 +840,18 @@
error = EAFNOSUPPORT;
break;
+ case SIOCGIFMTU:
+ break;
+
+ case SIOCSIFMTU:
+ ifr = (struct ifreq *)data;
+ mtu = ifr->ifr_mtu;
+ /* RFC 4213 3.2 ideal world MTU */
+ if (mtu < IPV6_MINMTU || mtu > IF_MAXMTU - 20)
+ return (EINVAL);
+ ifp->if_mtu = mtu;
+ break;
+
default:
error = EINVAL;
break;
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/net/if_tap.c
--- a/head/sys/net/if_tap.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/net/if_tap.c Wed Jul 25 16:47:10 2012 +0300
@@ -31,7 +31,7 @@
*/
/*
- * $FreeBSD: head/sys/net/if_tap.c 227459 2011-11-11 22:57:52Z brooks $
+ * $FreeBSD: head/sys/net/if_tap.c 238183 2012-07-06 23:17:30Z emaste $
* $Id: if_tap.c,v 0.21 2000/07/23 21:46:02 max Exp $
*/
@@ -42,6 +42,7 @@
#include <sys/conf.h>
#include <sys/fcntl.h>
#include <sys/filio.h>
+#include <sys/jail.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
@@ -64,8 +65,10 @@
#include <net/if.h>
#include <net/if_clone.h>
#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
#include <net/route.h>
-#include <net/if_types.h>
+#include <net/vnet.h>
#include <netinet/in.h>
@@ -214,6 +217,7 @@
KASSERT(!(tp->tap_flags & TAP_OPEN),
("%s flags is out of sync", ifp->if_xname));
+ CURVNET_SET(ifp->if_vnet);
seldrain(&tp->tap_rsel);
knlist_destroy(&tp->tap_rsel.si_note);
destroy_dev(tp->tap_dev);
@@ -222,6 +226,7 @@
mtx_destroy(&tp->tap_mtx);
free(tp, M_TAP);
+ CURVNET_RESTORE();
}
static void
@@ -363,6 +368,7 @@
if (unit == -1)
append_unit = 1;
+ CURVNET_SET(CRED_TO_VNET(cred));
/* find any existing device, or allocate new unit number */
i = clone_create(&tapclones, &tap_cdevsw, &unit, dev, extra);
if (i) {
@@ -381,6 +387,7 @@
}
if_clone_create(name, namelen, NULL);
+ CURVNET_RESTORE();
} /* tapclone */
@@ -521,6 +528,7 @@
/* junk all pending output */
mtx_lock(&tp->tap_mtx);
+ CURVNET_SET(ifp->if_vnet);
IF_DRAIN(&ifp->if_snd);
/*
@@ -544,6 +552,8 @@
}
if_link_state_change(ifp, LINK_STATE_DOWN);
+ CURVNET_RESTORE();
+
funsetown(&tp->tap_sigio);
selwakeuppri(&tp->tap_rsel, PZERO+1);
KNOTE_LOCKED(&tp->tap_rsel.si_note, 0);
@@ -593,7 +603,8 @@
struct tap_softc *tp = ifp->if_softc;
struct ifreq *ifr = (struct ifreq *)data;
struct ifstat *ifs = NULL;
- int dummy;
+ struct ifmediareq *ifmr = NULL;
+ int dummy, error = 0;
switch (cmd) {
case SIOCSIFFLAGS: /* XXX -- just like vmnet does */
@@ -601,6 +612,22 @@
case SIOCDELMULTI:
break;
+ case SIOCGIFMEDIA:
+ ifmr = (struct ifmediareq *)data;
+ dummy = ifmr->ifm_count;
+ ifmr->ifm_count = 1;
+ ifmr->ifm_status = IFM_AVALID;
+ ifmr->ifm_active = IFM_ETHER;
+ if (tp->tap_flags & TAP_OPEN)
+ ifmr->ifm_status |= IFM_ACTIVE;
+ ifmr->ifm_current = ifmr->ifm_active;
+ if (dummy >= 1) {
+ int media = IFM_ETHER;
+ error = copyout(&media, ifmr->ifm_ulist,
+ sizeof(int));
+ }
+ break;
+
case SIOCSIFMTU:
ifp->if_mtu = ifr->ifr_mtu;
break;
@@ -617,11 +644,11 @@
break;
default:
- return (ether_ioctl(ifp, cmd, data));
- /* NOT REACHED */
+ error = ether_ioctl(ifp, cmd, data);
+ break;
}
- return (0);
+ return (error);
} /* tapifioctl */
@@ -945,7 +972,9 @@
}
/* Pass packet up to parent. */
+ CURVNET_SET(ifp->if_vnet);
(*ifp->if_input)(ifp, m);
+ CURVNET_RESTORE();
ifp->if_ipackets ++; /* ibytes are counted in parent */
return (0);
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/net/if_var.h
--- a/head/sys/net/if_var.h Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/net/if_var.h Wed Jul 25 16:47:10 2012 +0300
@@ -27,7 +27,7 @@
* SUCH DAMAGE.
*
* From: @(#)if.h 8.1 (Berkeley) 6/10/93
- * $FreeBSD: head/sys/net/if_var.h 233202 2012-03-19 21:09:12Z jhb $
+ * $FreeBSD: head/sys/net/if_var.h 237263 2012-06-19 07:34:13Z np $
*/
#ifndef _NET_IF_VAR_H_
@@ -712,6 +712,8 @@
#define IF_MINMTU 72
#define IF_MAXMTU 65535
+#define TOEDEV(ifp) ((ifp)->if_llsoftc)
+
#endif /* _KERNEL */
/*
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/net/if_vlan.c
--- a/head/sys/net/if_vlan.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/net/if_vlan.c Wed Jul 25 16:47:10 2012 +0300
@@ -39,7 +39,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/net/if_vlan.c 230026 2012-01-12 18:39:37Z rwatson $");
+__FBSDID("$FreeBSD: head/sys/net/if_vlan.c 237263 2012-06-19 07:34:13Z np $");
#include "opt_vlan.h"
@@ -746,8 +746,8 @@
vlan_trunk_cap_p = NULL;
vlan_trunkdev_p = NULL;
vlan_tag_p = NULL;
- vlan_cookie_p = vlan_cookie;
- vlan_setcookie_p = vlan_setcookie;
+ vlan_cookie_p = NULL;
+ vlan_setcookie_p = NULL;
vlan_devat_p = NULL;
VLAN_LOCK_DESTROY();
if (bootverbose)
@@ -1503,6 +1503,22 @@
ifp->if_capenable &= ~(p->if_capenable & IFCAP_TSO);
ifp->if_hwassist &= ~(p->if_hwassist & CSUM_TSO);
}
+
+ /*
+ * If the parent interface can offload TCP connections over VLANs then
+ * propagate its TOE capability to the VLAN interface.
+ *
+ * All TOE drivers in the tree today can deal with VLANs. If this
+ * changes then IFCAP_VLAN_TOE should be promoted to a full capability
+ * with its own bit.
+ */
+#define IFCAP_VLAN_TOE IFCAP_TOE
+ if (p->if_capabilities & IFCAP_VLAN_TOE)
+ ifp->if_capabilities |= p->if_capabilities & IFCAP_TOE;
+ if (p->if_capenable & IFCAP_VLAN_TOE) {
+ TOEDEV(ifp) = TOEDEV(p);
+ ifp->if_capenable |= p->if_capenable & IFCAP_TOE;
+ }
}
static void
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/net/route.h
--- a/head/sys/net/route.h Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/net/route.h Wed Jul 25 16:47:10 2012 +0300
@@ -27,7 +27,7 @@
* SUCH DAMAGE.
*
* @(#)route.h 8.4 (Berkeley) 1/9/95
- * $FreeBSD: head/sys/net/route.h 233113 2012-03-18 11:23:40Z bz $
+ * $FreeBSD: head/sys/net/route.h 238092 2012-07-04 07:37:53Z glebius $
*/
#ifndef _NET_ROUTE_H_
@@ -54,7 +54,8 @@
struct sockaddr ro_dst;
};
-#define RT_CACHING_CONTEXT 0x1
+#define RT_CACHING_CONTEXT 0x1 /* XXX: not used anywhere */
+#define RT_NORTREF 0x2 /* doesn't hold reference on ro_rt */
/*
* These numbers are used by reliable protocols for determining
@@ -341,6 +342,18 @@
RTFREE_LOCKED(_rt); \
} while (0)
+#define RO_RTFREE(_ro) do { \
+ if ((_ro)->ro_rt) { \
+ if ((_ro)->ro_flags & RT_NORTREF) { \
+ (_ro)->ro_flags &= ~RT_NORTREF; \
+ (_ro)->ro_rt = NULL; \
+ } else { \
+ RT_LOCK((_ro)->ro_rt); \
+ RTFREE_LOCKED((_ro)->ro_rt); \
+ } \
+ } \
+} while (0)
+
struct radix_node_head *rt_tables_get_rnh(int, int);
struct ifmultiaddr;
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/net/rtsock.c
--- a/head/sys/net/rtsock.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/net/rtsock.c Wed Jul 25 16:47:10 2012 +0300
@@ -27,7 +27,7 @@
* SUCH DAMAGE.
*
* @(#)rtsock.c 8.7 (Berkeley) 10/12/95
- * $FreeBSD: head/sys/net/rtsock.c 231505 2012-02-11 06:02:16Z bz $
+ * $FreeBSD: head/sys/net/rtsock.c 234572 2012-04-22 16:13:23Z melifaro $
*/
#include "opt_compat.h"
#include "opt_sctp.h"
@@ -1884,10 +1884,10 @@
for (error = 0; error == 0 && i <= lim; i++) {
rnh = rt_tables_get_rnh(req->td->td_proc->p_fibnum, i);
if (rnh != NULL) {
- RADIX_NODE_HEAD_LOCK(rnh);
+ RADIX_NODE_HEAD_RLOCK(rnh);
error = rnh->rnh_walktree(rnh,
sysctl_dumpentry, &w);
- RADIX_NODE_HEAD_UNLOCK(rnh);
+ RADIX_NODE_HEAD_RUNLOCK(rnh);
} else if (af != 0)
error = EAFNOSUPPORT;
}
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/net80211/_ieee80211.h
--- a/head/sys/net80211/_ieee80211.h Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/net80211/_ieee80211.h Wed Jul 25 16:47:10 2012 +0300
@@ -23,7 +23,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $FreeBSD: head/sys/net80211/_ieee80211.h 220935 2011-04-22 00:44:27Z adrian $
+ * $FreeBSD: head/sys/net80211/_ieee80211.h 237871 2012-07-01 04:25:49Z adrian $
*/
#ifndef _NET80211__IEEE80211_H_
#define _NET80211__IEEE80211_H_
@@ -242,6 +242,8 @@
(((_c)->ic_flags & (IEEE80211_CHAN_OFDM | IEEE80211_CHAN_DYN)) != 0)
#define IEEE80211_IS_CHAN_CCK(_c) \
(((_c)->ic_flags & (IEEE80211_CHAN_CCK | IEEE80211_CHAN_DYN)) != 0)
+#define IEEE80211_IS_CHAN_DYN(_c) \
+ (((_c)->ic_flags & IEEE80211_CHAN_DYN) == IEEE80211_CHAN_DYN)
#define IEEE80211_IS_CHAN_GFSK(_c) \
(((_c)->ic_flags & IEEE80211_CHAN_GFSK) != 0)
#define IEEE80211_IS_CHAN_TURBO(_c) \
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/net80211/ieee80211.h
--- a/head/sys/net80211/ieee80211.h Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/net80211/ieee80211.h Wed Jul 25 16:47:10 2012 +0300
@@ -23,7 +23,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $FreeBSD: head/sys/net80211/ieee80211.h 232480 2012-03-04 05:52:26Z adrian $
+ * $FreeBSD: head/sys/net80211/ieee80211.h 234892 2012-05-01 16:14:18Z monthadar $
*/
#ifndef _NET80211_IEEE80211_H_
#define _NET80211_IEEE80211_H_
@@ -333,6 +333,8 @@
#define IEEE80211_ACTION_CAT_BA 3 /* BA */
#define IEEE80211_ACTION_CAT_HT 7 /* HT */
#define IEEE80211_ACTION_CAT_MESH 13 /* Mesh */
+#define IEEE80211_ACTION_CAT_SELF_PROT 15 /* Self-protected */
+/* 16 - 125 reserved */
#define IEEE80211_ACTION_CAT_VENDOR 127 /* Vendor Specific */
#define IEEE80211_ACTION_HT_TXCHWIDTH 0 /* recommended xmit chan width*/
@@ -732,7 +734,7 @@
IEEE80211_ELEMID_MESHAWAKEW = 119,
IEEE80211_ELEMID_MESHBEACONT = 120,
/* 121-124 MMCAOP not implemented yet */
- IEEE80211_ELEMID_MESHPANN = 125, /* XXX: is GANN now, not used */
+ IEEE80211_ELEMID_MESHGANN = 125,
IEEE80211_ELEMID_MESHRANN = 126,
/* 127 Extended Capabilities */
/* 128-129 reserved */
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/net80211/ieee80211_action.c
--- a/head/sys/net80211/ieee80211_action.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/net80211/ieee80211_action.c Wed Jul 25 16:47:10 2012 +0300
@@ -25,7 +25,7 @@
#include <sys/cdefs.h>
#ifdef __FreeBSD__
-__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_action.c 232479 2012-03-04 05:49:39Z adrian $");
+__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_action.c 234874 2012-05-01 15:35:10Z monthadar $");
#endif
/*
@@ -94,7 +94,7 @@
break;
ht_send_action[act] = f;
return 0;
- case IEEE80211_ACTION_CAT_MESHPEERING:
+ case IEEE80211_ACTION_CAT_SELF_PROT:
if (act >= N(meshpl_send_action))
break;
meshpl_send_action[act] = f;
@@ -144,7 +144,7 @@
if (act < N(ht_send_action))
f = ht_send_action[act];
break;
- case IEEE80211_ACTION_CAT_MESHPEERING:
+ case IEEE80211_ACTION_CAT_SELF_PROT:
if (act < N(meshpl_send_action))
f = meshpl_send_action[act];
break;
@@ -215,7 +215,7 @@
break;
ht_recv_action[act] = f;
return 0;
- case IEEE80211_ACTION_CAT_MESHPEERING:
+ case IEEE80211_ACTION_CAT_SELF_PROT:
if (act >= N(meshpl_recv_action))
break;
meshpl_recv_action[act] = f;
@@ -269,7 +269,7 @@
if (ia->ia_action < N(ht_recv_action))
f = ht_recv_action[ia->ia_action];
break;
- case IEEE80211_ACTION_CAT_MESHPEERING:
+ case IEEE80211_ACTION_CAT_SELF_PROT:
if (ia->ia_action < N(meshpl_recv_action))
f = meshpl_recv_action[ia->ia_action];
break;
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/net80211/ieee80211_ddb.c
--- a/head/sys/net80211/ieee80211_ddb.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/net80211/ieee80211_ddb.c Wed Jul 25 16:47:10 2012 +0300
@@ -24,7 +24,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_ddb.c 234324 2012-04-15 20:29:39Z adrian $");
+__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_ddb.c 234877 2012-05-01 15:47:30Z monthadar $");
#include "opt_ddb.h"
#include "opt_wlan.h"
@@ -870,8 +870,10 @@
TAILQ_FOREACH(rt, &ms->ms_routes, rt_next) {
db_printf("entry %d:\tdest: %6D nexthop: %6D metric: %u", i,
rt->rt_dest, ":", rt->rt_nexthop, ":", rt->rt_metric);
+
db_printf("\tlifetime: %u lastseq: %u priv: %p\n",
- rt->rt_lifetime, rt->rt_lastmseq, rt->rt_priv);
+ ieee80211_mesh_rt_update(rt, 0),
+ rt->rt_lastmseq, rt->rt_priv);
i++;
}
}
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/net80211/ieee80211_ht.c
--- a/head/sys/net80211/ieee80211_ht.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/net80211/ieee80211_ht.c Wed Jul 25 16:47:10 2012 +0300
@@ -25,7 +25,7 @@
#include <sys/cdefs.h>
#ifdef __FreeBSD__
-__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_ht.c 234324 2012-04-15 20:29:39Z adrian $");
+__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_ht.c 235801 2012-05-22 19:37:12Z adrian $");
#endif
/*
@@ -2166,6 +2166,9 @@
}
}
+/* XXX */
+static void bar_start_timer(struct ieee80211_tx_ampdu *tap);
+
static void
bar_timeout(void *arg)
{
@@ -2184,11 +2187,34 @@
return;
/* XXX ? */
if (tap->txa_attempts >= ieee80211_bar_maxtries) {
+ struct ieee80211com *ic = ni->ni_ic;
+
ni->ni_vap->iv_stats.is_ampdu_bar_tx_fail++;
+ /*
+ * If (at least) the last BAR TX timeout was due to
+ * an ieee80211_send_bar() failures, then we need
+ * to make sure we notify the driver that a BAR
+ * TX did occur and fail. This gives the driver
+ * a chance to undo any queue pause that may
+ * have occured.
+ */
+ ic->ic_bar_response(ni, tap, 1);
ieee80211_ampdu_stop(ni, tap, IEEE80211_REASON_TIMEOUT);
} else {
ni->ni_vap->iv_stats.is_ampdu_bar_tx_retry++;
- ieee80211_send_bar(ni, tap, tap->txa_seqpending);
+ if (ieee80211_send_bar(ni, tap, tap->txa_seqpending) != 0) {
+ /*
+ * If ieee80211_send_bar() fails here, the
+ * timer may have stopped and/or the pending
+ * flag may be clear. Because of this,
+ * fake the BARPEND and reset the timer.
+ * A retransmission attempt will then occur
+ * during the next timeout.
+ */
+ /* XXX locking */
+ tap->txa_flags |= IEEE80211_AGGR_BARPEND;
+ bar_start_timer(tap);
+ }
}
}
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/net80211/ieee80211_hwmp.c
--- a/head/sys/net80211/ieee80211_hwmp.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/net80211/ieee80211_hwmp.c Wed Jul 25 16:47:10 2012 +0300
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
#ifdef __FreeBSD__
-__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_hwmp.c 232625 2012-03-06 21:20:16Z adrian $");
+__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_hwmp.c 234896 2012-05-01 16:18:38Z monthadar $");
#endif
/*
@@ -89,7 +89,8 @@
static int hwmp_send_preq(struct ieee80211_node *,
const uint8_t [IEEE80211_ADDR_LEN],
const uint8_t [IEEE80211_ADDR_LEN],
- struct ieee80211_meshpreq_ie *);
+ struct ieee80211_meshpreq_ie *,
+ struct timeval *, struct timeval *);
static void hwmp_recv_prep(struct ieee80211vap *, struct ieee80211_node *,
const struct ieee80211_frame *,
const struct ieee80211_meshprep_ie *);
@@ -104,6 +105,9 @@
const uint8_t [IEEE80211_ADDR_LEN],
const uint8_t [IEEE80211_ADDR_LEN],
struct ieee80211_meshperr_ie *);
+static void hwmp_senderror(struct ieee80211vap *,
+ const uint8_t [IEEE80211_ADDR_LEN],
+ struct ieee80211_mesh_route *, int);
static void hwmp_recv_rann(struct ieee80211vap *, struct ieee80211_node *,
const struct ieee80211_frame *,
const struct ieee80211_meshrann_ie *);
@@ -143,8 +147,7 @@
#define HWMP_SEQ_GT(a, b) ((int32_t)((a)-(b)) > 0)
#define HWMP_SEQ_GEQ(a, b) ((int32_t)((a)-(b)) >= 0)
-/* The longer one of the lifetime should be stored as new lifetime */
-#define MESH_ROUTE_LIFETIME_MAX(a, b) (a > b ? a : b)
+#define HWMP_SEQ_MAX(a, b) (a > b ? a : b)
/*
* Private extension of ieee80211_mesh_route.
@@ -153,14 +156,16 @@
ieee80211_hwmp_seq hr_seq; /* last HWMP seq seen from dst*/
ieee80211_hwmp_seq hr_preqid; /* last PREQ ID seen from dst */
ieee80211_hwmp_seq hr_origseq; /* seq. no. on our latest PREQ*/
- int hr_preqretries;
+ struct timeval hr_lastpreq; /* last time we sent a PREQ */
+ struct timeval hr_lastrootconf; /* last sent PREQ root conf */
+ int hr_preqretries; /* number of discoveries */
+ int hr_lastdiscovery; /* last discovery in ticks */
};
struct ieee80211_hwmp_state {
ieee80211_hwmp_seq hs_seq; /* next seq to be used */
ieee80211_hwmp_seq hs_preqid; /* next PREQ ID to be used */
- struct timeval hs_lastpreq; /* last time we sent a PREQ */
+ int hs_rootmode; /* proactive HWMP */
struct timeval hs_lastperr; /* last time we sent a PERR */
- int hs_rootmode; /* proactive HWMP */
struct callout hs_roottimer;
uint8_t hs_maxhops; /* max hop count */
};
@@ -170,13 +175,19 @@
static int ieee80211_hwmp_targetonly = 0;
SYSCTL_INT(_net_wlan_hwmp, OID_AUTO, targetonly, CTLTYPE_INT | CTLFLAG_RW,
&ieee80211_hwmp_targetonly, 0, "Set TO bit on generated PREQs");
-static int ieee80211_hwmp_replyforward = 1;
-SYSCTL_INT(_net_wlan_hwmp, OID_AUTO, replyforward, CTLTYPE_INT | CTLFLAG_RW,
- &ieee80211_hwmp_replyforward, 0, "Set RF bit on generated PREQs");
static int ieee80211_hwmp_pathtimeout = -1;
SYSCTL_PROC(_net_wlan_hwmp, OID_AUTO, pathlifetime, CTLTYPE_INT | CTLFLAG_RW,
&ieee80211_hwmp_pathtimeout, 0, ieee80211_sysctl_msecs_ticks, "I",
"path entry lifetime (ms)");
+static int ieee80211_hwmp_maxpreq_retries = -1;
+SYSCTL_PROC(_net_wlan_hwmp, OID_AUTO, maxpreq_retries, CTLTYPE_INT | CTLFLAG_RW,
+ &ieee80211_hwmp_maxpreq_retries, 0, ieee80211_sysctl_msecs_ticks, "I",
+ "maximum number of preq retries");
+static int ieee80211_hwmp_net_diameter_traversaltime = -1;
+SYSCTL_PROC(_net_wlan_hwmp, OID_AUTO, net_diameter_traversal_time,
+ CTLTYPE_INT | CTLFLAG_RW, &ieee80211_hwmp_net_diameter_traversaltime, 0,
+ ieee80211_sysctl_msecs_ticks, "I",
+ "estimate travelse time across the MBSS (ms)");
static int ieee80211_hwmp_roottimeout = -1;
SYSCTL_PROC(_net_wlan_hwmp, OID_AUTO, roottimeout, CTLTYPE_INT | CTLFLAG_RW,
&ieee80211_hwmp_roottimeout, 0, ieee80211_sysctl_msecs_ticks, "I",
@@ -189,6 +200,11 @@
SYSCTL_PROC(_net_wlan_hwmp, OID_AUTO, rannint, CTLTYPE_INT | CTLFLAG_RW,
&ieee80211_hwmp_rannint, 0, ieee80211_sysctl_msecs_ticks, "I",
"root announcement interval (ms)");
+static struct timeval ieee80211_hwmp_rootconfint = { 0, 0 };
+static int ieee80211_hwmp_rootconfint_internal = -1;
+SYSCTL_PROC(_net_wlan_hwmp, OID_AUTO, rootconfint, CTLTYPE_INT | CTLFLAG_RD,
+ &ieee80211_hwmp_rootconfint_internal, 0, ieee80211_sysctl_msecs_ticks, "I",
+ "root confirmation interval (ms) (read-only)");
#define IEEE80211_HWMP_DEFAULT_MAXHOPS 31
@@ -199,6 +215,7 @@
.mpp_ie = IEEE80211_MESHCONF_PATH_HWMP,
.mpp_discover = hwmp_discover,
.mpp_peerdown = hwmp_peerdown,
+ .mpp_senderror = hwmp_senderror,
.mpp_vattach = hwmp_vattach,
.mpp_vdetach = hwmp_vdetach,
.mpp_newstate = hwmp_newstate,
@@ -212,10 +229,25 @@
static void
ieee80211_hwmp_init(void)
{
+ /* Default values as per amendment */
ieee80211_hwmp_pathtimeout = msecs_to_ticks(5*1000);
ieee80211_hwmp_roottimeout = msecs_to_ticks(5*1000);
ieee80211_hwmp_rootint = msecs_to_ticks(2*1000);
ieee80211_hwmp_rannint = msecs_to_ticks(1*1000);
+ ieee80211_hwmp_rootconfint_internal = msecs_to_ticks(2*1000);
+ ieee80211_hwmp_maxpreq_retries = 3;
+ /*
+ * (TU): A measurement of time equal to 1024 μs,
+ * 500 TU is 512 ms.
+ */
+ ieee80211_hwmp_net_diameter_traversaltime = msecs_to_ticks(512);
+
+ /*
+ * NB: I dont know how to make SYSCTL_PROC that calls ms to ticks
+ * and return a struct timeval...
+ */
+ ieee80211_hwmp_rootconfint.tv_usec =
+ ieee80211_hwmp_rootconfint_internal * 1000;
/*
* Register action frame handler.
@@ -537,6 +569,7 @@
}
memcpy(&rann, mrann, sizeof(rann));
rann.rann_seq = LE_READ_4(&mrann->rann_seq);
+ rann.rann_interval = LE_READ_4(&mrann->rann_interval);
rann.rann_metric = LE_READ_4(&mrann->rann_metric);
hwmp_recv_rann(vap, ni, wh, &rann);
found++;
@@ -808,8 +841,8 @@
"%s", "send broadcast PREQ");
preq.preq_flags = IEEE80211_MESHPREQ_FLAGS_AM;
- if (ms->ms_flags & IEEE80211_MESHFLAGS_PORTAL)
- preq.preq_flags |= IEEE80211_MESHPREQ_FLAGS_PR;
+ if (ms->ms_flags & IEEE80211_MESHFLAGS_GATE)
+ preq.preq_flags |= IEEE80211_MESHPREQ_FLAGS_GATE;
if (hs->hs_rootmode == IEEE80211_HWMP_ROOTMODE_PROACTIVE)
preq.preq_flags |= IEEE80211_MESHPREQ_FLAGS_PP;
preq.preq_hopcount = 0;
@@ -822,10 +855,11 @@
preq.preq_tcount = 1;
IEEE80211_ADDR_COPY(PREQ_TADDR(0), broadcastaddr);
PREQ_TFLAGS(0) = IEEE80211_MESHPREQ_TFLAGS_TO |
- IEEE80211_MESHPREQ_TFLAGS_RF;
+ IEEE80211_MESHPREQ_TFLAGS_USN;
PREQ_TSEQ(0) = 0;
vap->iv_stats.is_hwmp_rootreqs++;
- hwmp_send_preq(vap->iv_bss, vap->iv_myaddr, broadcastaddr, &preq);
+ hwmp_send_preq(vap->iv_bss, vap->iv_myaddr, broadcastaddr, &preq,
+ NULL, NULL); /* NB: we enforce rate check ourself */
hwmp_rootmode_setup(vap);
}
#undef PREQ_TFLAGS
@@ -848,12 +882,13 @@
"%s", "send broadcast RANN");
rann.rann_flags = 0;
- if (ms->ms_flags & IEEE80211_MESHFLAGS_PORTAL)
- rann.rann_flags |= IEEE80211_MESHRANN_FLAGS_PR;
+ if (ms->ms_flags & IEEE80211_MESHFLAGS_GATE)
+ rann.rann_flags |= IEEE80211_MESHFLAGS_GATE;
rann.rann_hopcount = 0;
rann.rann_ttl = ms->ms_ttl;
IEEE80211_ADDR_COPY(rann.rann_addr, vap->iv_myaddr);
rann.rann_seq = ++hs->hs_seq;
+ rann.rann_interval = ieee80211_hwmp_rannint;
rann.rann_metric = IEEE80211_MESHLMETRIC_INITIALVAL;
vap->iv_stats.is_hwmp_rootrann++;
@@ -869,13 +904,14 @@
const struct ieee80211_frame *wh, const struct ieee80211_meshpreq_ie *preq)
{
struct ieee80211_mesh_state *ms = vap->iv_mesh;
- struct ieee80211_mesh_route *rt = NULL;
struct ieee80211_mesh_route *rtorig = NULL;
+ struct ieee80211_mesh_route *rtorig_ext = NULL;
struct ieee80211_mesh_route *rttarg = NULL;
struct ieee80211_hwmp_route *hrorig = NULL;
struct ieee80211_hwmp_route *hrtarg = NULL;
struct ieee80211_hwmp_state *hs = vap->iv_hwmp;
struct ieee80211_meshprep_ie prep;
+ ieee80211_hwmp_seq preqid; /* last seen preqid for orig */
if (ni == vap->iv_bss ||
ni->ni_mlstate != IEEE80211_NODE_MESH_ESTABLISHED)
@@ -888,16 +924,21 @@
return;
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
- "received PREQ, source %6D", preq->preq_origaddr, ":");
+ "received PREQ, orig %6D, targ(0) %6D", preq->preq_origaddr, ":",
+ PREQ_TADDR(0), ":");
/*
- * Acceptance criteria: if the PREQ is not for us or not broadcast
+ * Acceptance criteria: (if the PREQ is not for us or not broadcast,
+ * or an external mac address not proxied by us),
* AND forwarding is disabled, discard this PREQ.
- * XXX: need to check PROXY
*/
- if ((!IEEE80211_ADDR_EQ(vap->iv_myaddr, PREQ_TADDR(0)) ||
- !IEEE80211_IS_MULTICAST(PREQ_TADDR(0))) &&
- !(ms->ms_flags & IEEE80211_MESHFLAGS_FWD)) {
+ rttarg = ieee80211_mesh_rt_find(vap, PREQ_TADDR(0));
+ if (!(ms->ms_flags & IEEE80211_MESHFLAGS_FWD) &&
+ (!IEEE80211_ADDR_EQ(vap->iv_myaddr, PREQ_TADDR(0)) ||
+ !IEEE80211_IS_MULTICAST(PREQ_TADDR(0)) ||
+ (rttarg != NULL &&
+ rttarg->rt_flags & IEEE80211_MESHRT_FLAGS_PROXY &&
+ IEEE80211_ADDR_EQ(vap->iv_myaddr, rttarg->rt_mesh_gate)))) {
IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_HWMP,
preq->preq_origaddr, NULL, "%s", "not accepting PREQ");
return;
@@ -906,7 +947,6 @@
* Acceptance criteria: if unicast addressed
* AND no valid forwarding for Target of PREQ, discard this PREQ.
*/
- rttarg = ieee80211_mesh_rt_find(vap, PREQ_TADDR(0));
if(rttarg != NULL)
hrtarg = IEEE80211_MESH_ROUTE_PRIV(rttarg,
struct ieee80211_hwmp_route);
@@ -926,19 +966,26 @@
rtorig = ieee80211_mesh_rt_find(vap, preq->preq_origaddr);
if (rtorig == NULL) {
rtorig = ieee80211_mesh_rt_add(vap, preq->preq_origaddr);
+ if (rtorig == NULL) {
+ IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+ "unable to add orig path to %6D",
+ preq->preq_origaddr, ":");
+ vap->iv_stats.is_mesh_rtaddfailed++;
+ return;
+ }
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
"adding originator %6D", preq->preq_origaddr, ":");
}
- if (rtorig == NULL) {
- /* XXX stat */
- return;
- }
hrorig = IEEE80211_MESH_ROUTE_PRIV(rtorig, struct ieee80211_hwmp_route);
+ /* record last seen preqid */
+ preqid = hrorig->hr_preqid;
+ hrorig->hr_preqid = HWMP_SEQ_MAX(hrorig->hr_preqid, preq->preq_id);
+
/* Data creation and update of forwarding information
* according to Table 11C-8 for originator mesh STA.
*/
- if(HWMP_SEQ_GT(preq->preq_origseq, hrorig->hr_seq) ||
+ if (HWMP_SEQ_GT(preq->preq_origseq, hrorig->hr_seq) ||
(HWMP_SEQ_EQ(preq->preq_origseq, hrorig->hr_seq) &&
preq->preq_metric < rtorig->rt_metric)) {
hrorig->hr_seq = preq->preq_origseq;
@@ -946,17 +993,19 @@
rtorig->rt_metric = preq->preq_metric +
ms->ms_pmetric->mpm_metric(ni);
rtorig->rt_nhops = preq->preq_hopcount + 1;
- rtorig->rt_lifetime = MESH_ROUTE_LIFETIME_MAX(
- preq->preq_lifetime, rtorig->rt_lifetime);
+ ieee80211_mesh_rt_update(rtorig, preq->preq_lifetime);
/* path to orig is valid now */
rtorig->rt_flags |= IEEE80211_MESHRT_FLAGS_VALID;
- }else if(hrtarg != NULL &&
- HWMP_SEQ_EQ(hrtarg->hr_seq, PREQ_TSEQ(0)) &&
- (rtorig->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0) {
+ }else if ((hrtarg != NULL &&
+ HWMP_SEQ_EQ(hrtarg->hr_seq, PREQ_TSEQ(0)) &&
+ ((rtorig->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0)) ||
+ preqid >= preq->preq_id) {
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
- "discard PREQ from %6D, old seq no %u <= %u",
+ "discard PREQ from %6D, old seqno %u <= %u,"
+ " or old preqid %u < %u",
preq->preq_origaddr, ":",
- preq->preq_origseq, hrorig->hr_seq);
+ preq->preq_origseq, hrorig->hr_seq,
+ preq->preq_id, preqid);
return;
}
@@ -967,68 +1016,86 @@
/*
* Check if the PREQ is addressed to us.
+ * or a Proxy currently supplied by us.
*/
- if (IEEE80211_ADDR_EQ(vap->iv_myaddr, PREQ_TADDR(0))) {
- IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
- "reply to %6D", preq->preq_origaddr, ":");
+ if (IEEE80211_ADDR_EQ(vap->iv_myaddr, PREQ_TADDR(0)) ||
+ (rttarg != NULL &&
+ rttarg->rt_flags & IEEE80211_MESHRT_FLAGS_PROXY &&
+ rttarg->rt_flags & IEEE80211_MESHRT_FLAGS_VALID)) {
+ /*
+ * When we are the target we shall update our own HWMP seq
+ * number with max of (current and preq->seq) + 1
+ */
+ hs->hs_seq = HWMP_SEQ_MAX(hs->hs_seq, PREQ_TSEQ(0)) + 1;
+
+ prep.prep_flags = 0;
+ if (rttarg != NULL && /* if NULL it means we are the target */
+ rttarg->rt_flags & IEEE80211_MESHRT_FLAGS_PROXY) {
+ IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+ "reply for proxy %6D", rttarg->rt_dest, ":");
+ prep.prep_flags |= IEEE80211_MESHPREP_FLAGS_AE;
+ IEEE80211_ADDR_COPY(prep.prep_target_ext_addr,
+ rttarg->rt_dest);
+ /* update proxy seqno to HWMP seqno */
+ rttarg->rt_ext_seq = hs->hs_seq;
+ }
/*
* Build and send a PREP frame.
*/
- prep.prep_flags = 0;
prep.prep_hopcount = 0;
prep.prep_ttl = ms->ms_ttl;
IEEE80211_ADDR_COPY(prep.prep_targetaddr, vap->iv_myaddr);
- prep.prep_targetseq = ++hs->hs_seq;
+ prep.prep_targetseq = hs->hs_seq;
prep.prep_lifetime = preq->preq_lifetime;
prep.prep_metric = IEEE80211_MESHLMETRIC_INITIALVAL;
IEEE80211_ADDR_COPY(prep.prep_origaddr, preq->preq_origaddr);
prep.prep_origseq = preq->preq_origseq;
+
+ IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+ "reply to %6D", preq->preq_origaddr, ":");
hwmp_send_prep(ni, vap->iv_myaddr, wh->i_addr2, &prep);
- /*
- * Build the reverse path, if we don't have it already.
- */
- rt = ieee80211_mesh_rt_find(vap, preq->preq_origaddr);
- if (rt == NULL)
- hwmp_discover(vap, preq->preq_origaddr, NULL);
- else if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0)
- hwmp_discover(vap, rt->rt_dest, NULL);
return;
}
+ /* we may update our proxy information for the orig external */
+ else if (preq->preq_flags & IEEE80211_MESHPREQ_FLAGS_AE) {
+ rtorig_ext =
+ ieee80211_mesh_rt_find(vap, preq->preq_orig_ext_addr);
+ if (rtorig_ext == NULL) {
+ rtorig_ext = ieee80211_mesh_rt_add(vap,
+ preq->preq_orig_ext_addr);
+ if (rtorig_ext == NULL) {
+ IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+ "unable to add orig ext proxy to %6D",
+ preq->preq_orig_ext_addr, ":");
+ vap->iv_stats.is_mesh_rtaddfailed++;
+ return;
+ }
+ IEEE80211_ADDR_COPY(rtorig_ext->rt_mesh_gate,
+ preq->preq_origaddr);
+ }
+ rtorig_ext->rt_ext_seq = preq->preq_origseq;
+ ieee80211_mesh_rt_update(rtorig_ext, preq->preq_lifetime);
+ }
/*
* Proactive PREQ: reply with a proactive PREP to the
* root STA if requested.
*/
if (IEEE80211_ADDR_EQ(PREQ_TADDR(0), broadcastaddr) &&
- (PREQ_TFLAGS(0) &
- ((IEEE80211_MESHPREQ_TFLAGS_TO|IEEE80211_MESHPREQ_TFLAGS_RF) ==
- (IEEE80211_MESHPREQ_TFLAGS_TO|IEEE80211_MESHPREQ_TFLAGS_RF)))) {
- uint8_t rootmac[IEEE80211_ADDR_LEN];
-
- IEEE80211_ADDR_COPY(rootmac, preq->preq_origaddr);
- rt = ieee80211_mesh_rt_find(vap, rootmac);
- if (rt == NULL) {
- rt = ieee80211_mesh_rt_add(vap, rootmac);
- if (rt == NULL) {
- IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
- "unable to add root mesh path to %6D",
- rootmac, ":");
- vap->iv_stats.is_mesh_rtaddfailed++;
- return;
- }
- }
+ (PREQ_TFLAGS(0) & IEEE80211_MESHPREQ_TFLAGS_TO)) {
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
- "root mesh station @ %6D", rootmac, ":");
+ "root mesh station @ %6D", preq->preq_origaddr, ":");
/*
* Reply with a PREP if we don't have a path to the root
* or if the root sent us a proactive PREQ.
*/
- if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0 ||
+ if ((rtorig->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0 ||
(preq->preq_flags & IEEE80211_MESHPREQ_FLAGS_PP)) {
prep.prep_flags = 0;
prep.prep_hopcount = 0;
prep.prep_ttl = ms->ms_ttl;
- IEEE80211_ADDR_COPY(prep.prep_origaddr, rootmac);
+ IEEE80211_ADDR_COPY(prep.prep_origaddr,
+ preq->preq_origaddr);
prep.prep_origseq = preq->preq_origseq;
prep.prep_lifetime = preq->preq_lifetime;
prep.prep_metric = IEEE80211_MESHLMETRIC_INITIALVAL;
@@ -1036,109 +1103,69 @@
vap->iv_myaddr);
prep.prep_targetseq = ++hs->hs_seq;
hwmp_send_prep(vap->iv_bss, vap->iv_myaddr,
- broadcastaddr, &prep);
+ rtorig->rt_nexthop, &prep);
}
- hwmp_discover(vap, rootmac, NULL);
- return;
}
- rt = ieee80211_mesh_rt_find(vap, PREQ_TADDR(0));
/*
* Forwarding and Intermediate reply for PREQs with 1 target.
*/
- if (preq->preq_tcount == 1) {
+ if ((preq->preq_tcount == 1) && (preq->preq_ttl > 1) &&
+ (ms->ms_flags & IEEE80211_MESHFLAGS_FWD)) {
struct ieee80211_meshpreq_ie ppreq; /* propagated PREQ */
memcpy(&ppreq, preq, sizeof(ppreq));
+
/*
* We have a valid route to this node.
*/
- if (rt != NULL &&
- (rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID)) {
- if (preq->preq_ttl > 1 &&
- preq->preq_hopcount < hs->hs_maxhops) {
- IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
- "forward PREQ from %6D",
- preq->preq_origaddr, ":");
- /*
- * Propagate the original PREQ.
- * PREQ is unicast now to rt->rt_nexthop
- */
- ppreq.preq_flags &=
- ~IEEE80211_MESHPREQ_FLAGS_AM;
- ppreq.preq_hopcount += 1;
- ppreq.preq_ttl -= 1;
- ppreq.preq_metric +=
- ms->ms_pmetric->mpm_metric(ni);
- /*
- * Set TO and unset RF bits because we are
- * going to send a PREP next.
- */
- ppreq.preq_targets[0].target_flags |=
- IEEE80211_MESHPREQ_TFLAGS_TO;
- ppreq.preq_targets[0].target_flags &=
- ~IEEE80211_MESHPREQ_TFLAGS_RF;
- hwmp_send_preq(ni, vap->iv_myaddr,
- rt->rt_nexthop, &ppreq);
- }
+ if (rttarg != NULL &&
+ (rttarg->rt_flags & IEEE80211_MESHRT_FLAGS_VALID)) {
/*
* Check if we can send an intermediate Path Reply,
- * i.e., Target Only bit is not set.
+ * i.e., Target Only bit is not set and target is not
+ * the MAC broadcast address.
*/
- if (!(PREQ_TFLAGS(0) & IEEE80211_MESHPREQ_TFLAGS_TO)) {
+ if (!(PREQ_TFLAGS(0) & IEEE80211_MESHPREQ_TFLAGS_TO) &&
+ !IEEE80211_ADDR_EQ(PREQ_TADDR(0), broadcastaddr)) {
struct ieee80211_meshprep_ie prep;
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
"intermediate reply for PREQ from %6D",
preq->preq_origaddr, ":");
prep.prep_flags = 0;
- prep.prep_hopcount = rt->rt_nhops + 1;
+ prep.prep_hopcount = rttarg->rt_nhops;
prep.prep_ttl = ms->ms_ttl;
IEEE80211_ADDR_COPY(&prep.prep_targetaddr,
PREQ_TADDR(0));
- prep.prep_targetseq = hrorig->hr_seq;
+ prep.prep_targetseq = hrtarg->hr_seq;
prep.prep_lifetime = preq->preq_lifetime;
- prep.prep_metric = rt->rt_metric +
- ms->ms_pmetric->mpm_metric(ni);
+ prep.prep_metric =rttarg->rt_metric;
IEEE80211_ADDR_COPY(&prep.prep_origaddr,
preq->preq_origaddr);
prep.prep_origseq = hrorig->hr_seq;
hwmp_send_prep(ni, vap->iv_myaddr,
- broadcastaddr, &prep);
+ rtorig->rt_nexthop, &prep);
+
+ /*
+ * Set TO and unset RF bits because we have
+ * sent a PREP.
+ */
+ ppreq.preq_targets[0].target_flags |=
+ IEEE80211_MESHPREQ_TFLAGS_TO;
}
- /*
- * We have no information about this path,
- * propagate the PREQ.
- */
- } else if (preq->preq_ttl > 1 &&
- preq->preq_hopcount < hs->hs_maxhops) {
- if (rt == NULL) {
- rt = ieee80211_mesh_rt_add(vap, PREQ_TADDR(0));
- if (rt == NULL) {
- IEEE80211_NOTE(vap,
- IEEE80211_MSG_HWMP, ni,
- "unable to add PREQ path to %6D",
- PREQ_TADDR(0), ":");
- vap->iv_stats.is_mesh_rtaddfailed++;
- return;
- }
- }
- rt->rt_metric = preq->preq_metric;
- rt->rt_lifetime = preq->preq_lifetime;
- hrorig = IEEE80211_MESH_ROUTE_PRIV(rt,
- struct ieee80211_hwmp_route);
- hrorig->hr_seq = preq->preq_origseq;
- hrorig->hr_preqid = preq->preq_id;
+ }
- IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
- "forward PREQ from %6D",
- preq->preq_origaddr, ":");
- ppreq.preq_hopcount += 1;
- ppreq.preq_ttl -= 1;
- ppreq.preq_metric += ms->ms_pmetric->mpm_metric(ni);
- hwmp_send_preq(ni, vap->iv_myaddr, broadcastaddr,
- &ppreq);
- }
+ IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+ "forward PREQ from %6D",
+ preq->preq_origaddr, ":");
+ ppreq.preq_hopcount += 1;
+ ppreq.preq_ttl -= 1;
+ ppreq.preq_metric += ms->ms_pmetric->mpm_metric(ni);
+
+ /* don't do PREQ ratecheck when we propagate */
+ hwmp_send_preq(ni, vap->iv_myaddr, broadcastaddr,
+ &ppreq, NULL, NULL);
}
}
#undef PREQ_TFLAGS
@@ -1149,16 +1176,19 @@
hwmp_send_preq(struct ieee80211_node *ni,
const uint8_t sa[IEEE80211_ADDR_LEN],
const uint8_t da[IEEE80211_ADDR_LEN],
- struct ieee80211_meshpreq_ie *preq)
+ struct ieee80211_meshpreq_ie *preq,
+ struct timeval *last, struct timeval *minint)
{
- struct ieee80211_hwmp_state *hs = ni->ni_vap->iv_hwmp;
/*
* Enforce PREQ interval.
+ * NB: Proactive ROOT PREQs rate is handled by cb task.
*/
- if (ratecheck(&hs->hs_lastpreq, &ieee80211_hwmp_preqminint) == 0)
- return EALREADY;
- getmicrouptime(&hs->hs_lastpreq);
+ if (last != NULL && minint != NULL) {
+ if (ratecheck(last, minint) == 0)
+ return EALREADY; /* XXX: we should postpone */
+ getmicrouptime(last);
+ }
/*
* mesh preq action frame format
@@ -1180,62 +1210,70 @@
hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni,
const struct ieee80211_frame *wh, const struct ieee80211_meshprep_ie *prep)
{
+#define IS_PROXY(rt) (rt->rt_flags & IEEE80211_MESHRT_FLAGS_PROXY)
+#define PROXIED_BY_US(rt) \
+ (IEEE80211_ADDR_EQ(vap->iv_myaddr, rt->rt_mesh_gate))
struct ieee80211_mesh_state *ms = vap->iv_mesh;
struct ieee80211_hwmp_state *hs = vap->iv_hwmp;
struct ieee80211_mesh_route *rt = NULL;
+ struct ieee80211_mesh_route *rtorig = NULL;
+ 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;
- /*
- * Acceptance criteria: if the corresponding PREQ was not generated
- * by us and forwarding is disabled, discard this PREP.
- */
if (ni == vap->iv_bss ||
ni->ni_mlstate != IEEE80211_NODE_MESH_ESTABLISHED)
return;
- if (!IEEE80211_ADDR_EQ(vap->iv_myaddr, prep->prep_origaddr) &&
- !(ms->ms_flags & IEEE80211_MESHFLAGS_FWD))
- return;
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
- "received PREP from %6D", prep->prep_targetaddr, ":");
+ "received PREP, orig %6D, targ %6D", prep->prep_origaddr, ":",
+ prep->prep_targetaddr, ":");
+ /*
+ * Acceptance criteria: (If the corresponding PREP was not generated
+ * by us OR not generated by an external mac that is not proxied by us)
+ * AND forwarding is disabled, discard this PREP.
+ */
+ rtorig = ieee80211_mesh_rt_find(vap, prep->prep_origaddr);
+ if ((!IEEE80211_ADDR_EQ(vap->iv_myaddr, prep->prep_origaddr) ||
+ (rtorig != NULL && IS_PROXY(rtorig) && !PROXIED_BY_US(rtorig))) &&
+ !(ms->ms_flags & IEEE80211_MESHFLAGS_FWD)){
+ IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+ "discard PREP, orig(%6D) not proxied or generated by us",
+ prep->prep_origaddr, ":");
+ return;
+ }
+
+ /* PREP ACCEPTED */
+
+ /*
+ * If accepted shall create or update the active forwarding information
+ * it maintains for the target mesh STA of the PREP (according to the
+ * rules defined in 13.10.8.4). If the conditions for creating or
+ * updating the forwarding information have not been met in those
+ * rules, no further steps are applied to the PREP.
+ * [OPTIONAL]: update forwarding information to TA if metric improves.
+ */
rt = ieee80211_mesh_rt_find(vap, prep->prep_targetaddr);
if (rt == NULL) {
- /*
- * If we have no entry this could be a reply to a root PREQ.
- * XXX: not true anymore cause we dont create entry for target
- * when propagating PREQs like the old code did.
- */
- if (hs->hs_rootmode != IEEE80211_HWMP_ROOTMODE_DISABLED) {
- rt = ieee80211_mesh_rt_add(vap, prep->prep_targetaddr);
- if (rt == NULL) {
- IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP,
- ni, "unable to add PREP path to %6D",
- prep->prep_targetaddr, ":");
- vap->iv_stats.is_mesh_rtaddfailed++;
- return;
- }
- IEEE80211_ADDR_COPY(rt->rt_nexthop, wh->i_addr2);
- rt->rt_nhops = prep->prep_hopcount;
- rt->rt_lifetime = prep->prep_lifetime;
- rt->rt_metric = prep->prep_metric;
- rt->rt_flags |= IEEE80211_MESHRT_FLAGS_VALID;
+ rt = ieee80211_mesh_rt_add(vap, prep->prep_targetaddr);
+ if (rt == NULL) {
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
- "add root path to %6D nhops %d metric %lu (PREP)",
- prep->prep_targetaddr, ":",
- rt->rt_nhops, rt->rt_metric);
+ "unable to add PREP path to %6D",
+ prep->prep_targetaddr, ":");
+ vap->iv_stats.is_mesh_rtaddfailed++;
return;
}
- return;
+ IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+ "adding target %6D", prep->prep_targetaddr, ":");
}
- /*
- * Sequence number validation.
- */
hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route);
+ /* update path metric */
+ metric = prep->prep_metric + ms->ms_pmetric->mpm_metric(ni);
if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID)) {
if (HWMP_SEQ_LT(prep->prep_targetseq, hr->hr_seq)) {
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
@@ -1244,7 +1282,7 @@
prep->prep_targetseq, hr->hr_seq);
return;
} else if (HWMP_SEQ_LEQ(prep->prep_targetseq, hr->hr_seq) &&
- prep->prep_metric > rt->rt_metric) {
+ metric > rt->rt_metric) {
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
"discard PREP from %6D, new metric %u > %u",
prep->prep_targetaddr, ":",
@@ -1253,13 +1291,46 @@
}
}
+ IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+ "%s path to %6D, hopcount %d:%d metric %d:%d",
+ rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID ?
+ "prefer" : "update",
+ prep->prep_targetaddr, ":",
+ rt->rt_nhops, prep->prep_hopcount,
+ rt->rt_metric, metric);
+
hr->hr_seq = prep->prep_targetseq;
+ hr->hr_preqretries = 0;
+ IEEE80211_ADDR_COPY(rt->rt_nexthop, ni->ni_macaddr);
+ rt->rt_metric = metric;
+ rt->rt_nhops = prep->prep_hopcount + 1;
+ ieee80211_mesh_rt_update(rt, prep->prep_lifetime);
+ if (rt->rt_flags & IEEE80211_MESHRT_FLAGS_DISCOVER) {
+ /* discovery complete */
+ rt->rt_flags &= ~IEEE80211_MESHRT_FLAGS_DISCOVER;
+ }
+ rt->rt_flags |= IEEE80211_MESHRT_FLAGS_VALID; /* mark valid */
+
/*
- * If it's NOT for us, propagate the PREP.
+ * If it's NOT for us, propagate the PREP
*/
if (!IEEE80211_ADDR_EQ(vap->iv_myaddr, prep->prep_origaddr) &&
- prep->prep_ttl > 1 && prep->prep_hopcount < hs->hs_maxhops) {
+ prep->prep_ttl > 1 &&
+ prep->prep_hopcount < hs->hs_maxhops) {
struct ieee80211_meshprep_ie pprep; /* propagated PREP */
+ /*
+ * NB: We should already have setup the path to orig
+ * mesh STA when we propagated PREQ to target mesh STA,
+ * no PREP is generated without a corresponding PREQ.
+ * XXX: for now just ignore.
+ */
+ if (rtorig == NULL) {
+ IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+ "received PREP for an unknown orig(%6D)",
+ prep->prep_origaddr, ":");
+ return;
+ }
+
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
"propagate PREP from %6D",
prep->prep_targetaddr, ":");
@@ -1268,54 +1339,53 @@
pprep.prep_hopcount += 1;
pprep.prep_ttl -= 1;
pprep.prep_metric += ms->ms_pmetric->mpm_metric(ni);
- hwmp_send_prep(ni, vap->iv_myaddr, broadcastaddr, &pprep);
+ hwmp_send_prep(ni, vap->iv_myaddr, rtorig->rt_nexthop, &pprep);
+
+ /* precursor list for the Target Mesh STA Address is updated */
}
- hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route);
- if (rt->rt_flags & IEEE80211_MESHRT_FLAGS_PROXY) {
- /* NB: never clobber a proxy entry */;
+
+ /*
+ * Check if we received a PREP w/ AE and store target external address.
+ * We may store target external address if recevied PREP w/ AE
+ * and we are not final destination
+ */
+ if (prep->prep_flags & IEEE80211_MESHPREP_FLAGS_AE) {
+ rtext = ieee80211_mesh_rt_find(vap,
+ prep->prep_target_ext_addr);
+ if (rtext == NULL) {
+ rtext = ieee80211_mesh_rt_add(vap,
+ prep->prep_target_ext_addr);
+ if (rtext == NULL) {
+ IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+ "unable to add PREP path to proxy %6D",
+ prep->prep_targetaddr, ":");
+ vap->iv_stats.is_mesh_rtaddfailed++;
+ return;
+ }
+ }
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
- "discard PREP for %6D, route is marked PROXY",
- prep->prep_targetaddr, ":");
- vap->iv_stats.is_hwmp_proxy++;
- /* NB: first path discovery always fails */
- } else if (hr->hr_origseq == 0 ||
- prep->prep_origseq == hr->hr_origseq) {
+ "%s path to %6D, hopcount %d:%d metric %d:%d",
+ rtext->rt_flags & IEEE80211_MESHRT_FLAGS_VALID ?
+ "prefer" : "update",
+ prep->prep_target_ext_addr, ":",
+ rtext->rt_nhops, prep->prep_hopcount,
+ rtext->rt_metric, metric);
+
+ rtext->rt_flags = IEEE80211_MESHRT_FLAGS_PROXY |
+ IEEE80211_MESHRT_FLAGS_VALID;
+ IEEE80211_ADDR_COPY(rtext->rt_dest,
+ prep->prep_target_ext_addr);
+ IEEE80211_ADDR_COPY(rtext->rt_mesh_gate,
+ prep->prep_targetaddr);
+ IEEE80211_ADDR_COPY(rtext->rt_nexthop, wh->i_addr2);
+ rtext->rt_metric = metric;
+ rtext->rt_lifetime = prep->prep_lifetime;
+ rtext->rt_nhops = prep->prep_hopcount + 1;
+ rtext->rt_ext_seq = prep->prep_origseq; /* new proxy seq */
/*
- * Check if we already have a path to this node.
- * If we do, check if this path reply contains a
- * better route.
+ * XXX: proxy entries have no HWMP priv data,
+ * nullify them to be sure?
*/
- if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0 ||
- (prep->prep_hopcount < rt->rt_nhops ||
- prep->prep_metric < rt->rt_metric)) {
- hr->hr_origseq = prep->prep_origseq;
- metric = prep->prep_metric +
- ms->ms_pmetric->mpm_metric(ni);
- IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
- "%s path to %6D, hopcount %d:%d metric %d:%d",
- rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID ?
- "prefer" : "update",
- prep->prep_origaddr, ":",
- rt->rt_nhops, prep->prep_hopcount,
- rt->rt_metric, prep->prep_metric);
- IEEE80211_ADDR_COPY(rt->rt_nexthop, wh->i_addr2);
- rt->rt_nhops = prep->prep_hopcount + 1;
- rt->rt_lifetime = prep->prep_lifetime;
- rt->rt_metric = metric;
- rt->rt_flags |= IEEE80211_MESHRT_FLAGS_VALID;
- } else {
- IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
- "ignore PREP for %6D, hopcount %d:%d metric %d:%d",
- prep->prep_targetaddr, ":",
- rt->rt_nhops, prep->prep_hopcount,
- rt->rt_metric, prep->prep_metric);
- }
- } else {
- IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
- "discard PREP for %6D, wrong orig seqno %u != %u",
- prep->prep_targetaddr, ":", prep->prep_origseq,
- hr->hr_origseq);
- vap->iv_stats.is_hwmp_wrongseq++;
}
/*
* Check for frames queued awaiting path discovery.
@@ -1324,9 +1394,11 @@
* stuck back on the stageq because there won't be
* a path.
*/
+ addr = prep->prep_flags & IEEE80211_MESHPREP_FLAGS_AE ?
+ prep->prep_target_ext_addr : prep->prep_targetaddr;
m = ieee80211_ageq_remove(&ic->ic_stageq,
(struct ieee80211_node *)(uintptr_t)
- ieee80211_mac_hash(ic, rt->rt_dest));
+ ieee80211_mac_hash(ic, addr)); /* either dest or ext_dest */
for (; m != NULL; m = next) {
next = m->m_nextpkt;
m->m_nextpkt = NULL;
@@ -1334,6 +1406,8 @@
"flush queued frame %p len %d", m, m->m_pkthdr.len);
ifp->if_transmit(ifp, m);
}
+#undef IS_PROXY
+#undef PROXIED_BY_US
}
static int
@@ -1386,7 +1460,7 @@
PERR_DFLAGS(0) |= IEEE80211_MESHPERR_DFLAGS_USN;
PERR_DFLAGS(0) |= IEEE80211_MESHPERR_DFLAGS_RC;
IEEE80211_ADDR_COPY(PERR_DADDR(0), rt->rt_dest);
- PERR_DSEQ(0) = hr->hr_seq;
+ PERR_DSEQ(0) = ++hr->hr_seq;
PERR_DRCODE(0) = IEEE80211_REASON_MESH_PERR_DEST_UNREACH;
/* NB: flush everything passing through peer */
ieee80211_mesh_rt_flush_peer(vap, ni->ni_macaddr);
@@ -1397,60 +1471,117 @@
#undef PERR_DSEQ
#undef PERR_DRCODE
-#define PERR_DFLAGS(n) perr->perr_dests[n].dest_flags
-#define PERR_DADDR(n) perr->perr_dests[n].dest_addr
-#define PERR_DSEQ(n) perr->perr_dests[n].dest_seq
-#define PERR_DRCODE(n) perr->perr_dests[n].dest_rcode
+#define PERR_DFLAGS(n) perr->perr_dests[n].dest_flags
+#define PERR_DADDR(n) perr->perr_dests[n].dest_addr
+#define PERR_DSEQ(n) perr->perr_dests[n].dest_seq
+#define PERR_DEXTADDR(n) perr->perr_dests[n].dest_ext_addr
+#define PERR_DRCODE(n) perr->perr_dests[n].dest_rcode
static void
hwmp_recv_perr(struct ieee80211vap *vap, struct ieee80211_node *ni,
const struct ieee80211_frame *wh, const struct ieee80211_meshperr_ie *perr)
{
struct ieee80211_mesh_state *ms = vap->iv_mesh;
struct ieee80211_mesh_route *rt = NULL;
+ struct ieee80211_mesh_route *rt_ext = NULL;
struct ieee80211_hwmp_route *hr;
- struct ieee80211_meshperr_ie pperr;
- int i, forward = 0;
+ struct ieee80211_meshperr_ie *pperr = NULL;
+ int i, j = 0, forward = 0;
+
+ if (ni == vap->iv_bss ||
+ ni->ni_mlstate != IEEE80211_NODE_MESH_ESTABLISHED)
+ return;
+
+ IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+ "received PERR from %6D", wh->i_addr2, ":");
/*
- * Acceptance criteria: check if we received a PERR from a
- * neighbor and forwarding is enabled.
+ * if forwarding is true, prepare pperr
*/
- if (ni == vap->iv_bss ||
- ni->ni_mlstate != IEEE80211_NODE_MESH_ESTABLISHED ||
- !(ms->ms_flags & IEEE80211_MESHFLAGS_FWD))
- return;
+ if (ms->ms_flags & IEEE80211_MESHFLAGS_FWD) {
+ forward = 1;
+ pperr = malloc(sizeof(*perr) + 31*sizeof(*perr->perr_dests),
+ M_80211_MESH_PERR, M_NOWAIT); /* XXX: magic number, 32 err dests */
+ }
+
/*
- * Find all routing entries that match and delete them.
+ * Acceptance criteria: check if we have forwarding information
+ * stored about destination, and that nexthop == TA of this PERR.
+ * NB: we also build a new PERR to propagate in case we should forward.
*/
for (i = 0; i < perr->perr_ndests; i++) {
rt = ieee80211_mesh_rt_find(vap, PERR_DADDR(i));
- if (rt == NULL)
+ if (rt == NULL || rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID)
continue;
+ if (!IEEE80211_ADDR_EQ(rt->rt_nexthop, wh->i_addr2))
+ continue;
+
+ /* found and accepted a PERR ndest element, process it... */
+ if (forward)
+ memcpy(&pperr->perr_dests[j], &perr->perr_dests[i],
+ sizeof(*perr->perr_dests));
hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route);
- if (!(PERR_DFLAGS(0) & IEEE80211_MESHPERR_DFLAGS_USN) &&
- HWMP_SEQ_GEQ(PERR_DSEQ(i), hr->hr_seq)) {
- ieee80211_mesh_rt_del(vap, rt->rt_dest);
- ieee80211_mesh_rt_flush_peer(vap, rt->rt_dest);
- rt = NULL;
- forward = 1;
+ switch(PERR_DFLAGS(i)) {
+ case (IEEE80211_REASON_MESH_PERR_NO_FI):
+ if (PERR_DSEQ(i) == 0) {
+ hr->hr_seq++;
+ if (forward) {
+ pperr->perr_dests[j].dest_seq =
+ hr->hr_seq;
+ }
+ } else {
+ hr->hr_seq = PERR_DSEQ(i);
+ }
+ rt->rt_flags &= ~IEEE80211_MESHRT_FLAGS_VALID;
+ j++;
+ break;
+ case (IEEE80211_REASON_MESH_PERR_DEST_UNREACH):
+ if(HWMP_SEQ_GT(PERR_DSEQ(i), hr->hr_seq)) {
+ hr->hr_seq = PERR_DSEQ(i);
+ rt->rt_flags &= ~IEEE80211_MESHRT_FLAGS_VALID;
+ j++;
+ }
+ break;
+ case (IEEE80211_REASON_MESH_PERR_NO_PROXY):
+ rt_ext = ieee80211_mesh_rt_find(vap, PERR_DEXTADDR(i));
+ if (rt_ext != NULL) {
+ rt_ext->rt_flags &=
+ ~IEEE80211_MESHRT_FLAGS_VALID;
+ j++;
+ }
+ break;
+ default:
+ IEEE80211_DISCARD(vap, IEEE80211_MSG_HWMP, wh, NULL,
+ "PERR, unknown reason code %u\n", PERR_DFLAGS(i));
+ goto done; /* XXX: stats?? */
}
+ ieee80211_mesh_rt_flush_peer(vap, rt->rt_dest);
+ KASSERT(j < 32, ("PERR, error ndest >= 32 (%u)", j));
}
+ if (j == 0) {
+ IEEE80211_DISCARD(vap, IEEE80211_MSG_HWMP, wh, NULL, "%s",
+ "PERR not accepted");
+ goto done; /* XXX: stats?? */
+ }
+
/*
* Propagate the PERR if we previously found it on our routing table.
- * XXX handle ndest > 1
*/
if (forward && perr->perr_ttl > 1) {
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
"propagate PERR from %6D", wh->i_addr2, ":");
- memcpy(&pperr, perr, sizeof(*perr));
- pperr.perr_ttl--;
+ pperr->perr_ndests = j;
+ pperr->perr_ttl--;
hwmp_send_perr(vap->iv_bss, vap->iv_myaddr, broadcastaddr,
- &pperr);
+ pperr);
}
+done:
+ if (pperr != NULL)
+ free(pperr, M_80211_MESH_PERR);
}
#undef PERR_DFLAGS
-#undef PEER_DADDR
+#undef PERR_DADDR
#undef PERR_DSEQ
+#undef PERR_DEXTADDR
#undef PERR_DRCODE
static int
@@ -1493,6 +1624,64 @@
return hwmp_send_action(ni, sa, da, (uint8_t *)perr, perr->perr_len+2);
}
+/*
+ * Called from the rest of the net80211 code (mesh code for example).
+ * NB: IEEE80211_REASON_MESH_PERR_DEST_UNREACH can be trigger by the fact that
+ * a mesh STA is unable to forward an MSDU/MMPDU to a next-hop mesh STA.
+ */
+#define PERR_DFLAGS(n) perr.perr_dests[n].dest_flags
+#define PERR_DADDR(n) perr.perr_dests[n].dest_addr
+#define PERR_DSEQ(n) perr.perr_dests[n].dest_seq
+#define PERR_DEXTADDR(n) perr.perr_dests[n].dest_ext_addr
+#define PERR_DRCODE(n) perr.perr_dests[n].dest_rcode
+static void
+hwmp_senderror(struct ieee80211vap *vap,
+ const uint8_t addr[IEEE80211_ADDR_LEN],
+ struct ieee80211_mesh_route *rt, int rcode)
+{
+ struct ieee80211_mesh_state *ms = vap->iv_mesh;
+ struct ieee80211_hwmp_route *hr = NULL;
+ struct ieee80211_meshperr_ie perr;
+
+ if (rt != NULL)
+ hr = IEEE80211_MESH_ROUTE_PRIV(rt,
+ struct ieee80211_hwmp_route);
+
+ perr.perr_ndests = 1;
+ perr.perr_ttl = ms->ms_ttl;
+ PERR_DFLAGS(0) = 0;
+ PERR_DRCODE(0) = rcode;
+
+ switch (rcode) {
+ case IEEE80211_REASON_MESH_PERR_NO_FI:
+ IEEE80211_ADDR_COPY(PERR_DADDR(0), addr);
+ PERR_DSEQ(0) = 0; /* reserved */
+ break;
+ case IEEE80211_REASON_MESH_PERR_NO_PROXY:
+ KASSERT(rt != NULL, ("no proxy info for sending PERR"));
+ KASSERT(rt->rt_flags & IEEE80211_MESHRT_FLAGS_PROXY,
+ ("route is not marked proxy"));
+ PERR_DFLAGS(0) |= IEEE80211_MESHPERR_FLAGS_AE;
+ IEEE80211_ADDR_COPY(PERR_DADDR(0), vap->iv_myaddr);
+ PERR_DSEQ(0) = rt->rt_ext_seq;
+ IEEE80211_ADDR_COPY(PERR_DEXTADDR(0), addr);
+ break;
+ case IEEE80211_REASON_MESH_PERR_DEST_UNREACH:
+ KASSERT(rt != NULL, ("no route info for sending PERR"));
+ IEEE80211_ADDR_COPY(PERR_DADDR(0), addr);
+ PERR_DSEQ(0) = hr->hr_seq;
+ break;
+ default:
+ KASSERT(0, ("unknown reason code for HWMP PERR (%u)", rcode));
+ }
+ hwmp_send_perr(vap->iv_bss, vap->iv_myaddr, broadcastaddr, &perr);
+}
+#undef PERR_DFLAGS
+#undef PEER_DADDR
+#undef PERR_DSEQ
+#undef PERR_DEXTADDR
+#undef PERR_DRCODE
+
static void
hwmp_recv_rann(struct ieee80211vap *vap, struct ieee80211_node *ni,
const struct ieee80211_frame *wh, const struct ieee80211_meshrann_ie *rann)
@@ -1501,7 +1690,9 @@
struct ieee80211_hwmp_state *hs = vap->iv_hwmp;
struct ieee80211_mesh_route *rt = NULL;
struct ieee80211_hwmp_route *hr;
+ struct ieee80211_meshpreq_ie preq;
struct ieee80211_meshrann_ie prann;
+ uint32_t metric = 0;
if (ni == vap->iv_bss ||
ni->ni_mlstate != IEEE80211_NODE_MESH_ESTABLISHED ||
@@ -1509,27 +1700,74 @@
return;
rt = ieee80211_mesh_rt_find(vap, rann->rann_addr);
- /*
- * Discover the path to the root mesh STA.
- * If we already know it, propagate the RANN element.
- */
+ if (rt != NULL && rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) {
+ hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route);
+
+ /* Acceptance criteria: if RANN.seq < stored seq, discard RANN */
+ if (HWMP_SEQ_LT(rann->rann_seq, hr->hr_seq)) {
+ IEEE80211_DISCARD(vap, IEEE80211_MSG_HWMP, wh, NULL,
+ "RANN seq %u < %u", rann->rann_seq, hr->hr_seq);
+ return;
+ }
+
+ /* Acceptance criteria: if RANN.seq == stored seq AND
+ * RANN.metric > stored metric, discard RANN */
+ if (HWMP_SEQ_EQ(rann->rann_seq, hr->hr_seq) &&
+ rann->rann_metric > rt->rt_metric) {
+ IEEE80211_DISCARD(vap, IEEE80211_MSG_HWMP, wh, NULL,
+ "RANN metric %u > %u", rann->rann_metric, rt->rt_metric);
+ return;
+ }
+ }
+
+ /* RANN ACCEPTED */
+
+ ieee80211_hwmp_rannint = rann->rann_interval; /* XXX: mtx lock? */
+ metric = rann->rann_metric + ms->ms_pmetric->mpm_metric(ni);
+
if (rt == NULL) {
- hwmp_discover(vap, rann->rann_addr, NULL);
- return;
+ rt = ieee80211_mesh_rt_add(vap, rann->rann_addr);
+ if (rt == NULL) {
+ IEEE80211_DISCARD(vap, IEEE80211_MSG_HWMP, wh, NULL,
+ "unable to add mac for RANN root %6D",
+ rann->rann_addr, ":");
+ vap->iv_stats.is_mesh_rtaddfailed++;
+ return;
+ }
}
hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route);
- if (HWMP_SEQ_GT(rann->rann_seq, hr->hr_seq)) {
+ /* discovery timeout */
+ ieee80211_mesh_rt_update(rt,
+ ticks_to_msecs(ieee80211_hwmp_roottimeout));
+
+ preq.preq_flags = IEEE80211_MESHPREQ_FLAGS_AM;
+ preq.preq_hopcount = 0;
+ preq.preq_ttl = ms->ms_ttl;
+ preq.preq_id = 0; /* reserved */
+ IEEE80211_ADDR_COPY(preq.preq_origaddr, vap->iv_myaddr);
+ preq.preq_origseq = ++hs->hs_seq;
+ preq.preq_lifetime = ieee80211_hwmp_roottimeout;
+ preq.preq_metric = IEEE80211_MESHLMETRIC_INITIALVAL;
+ preq.preq_tcount = 1;
+ preq.preq_targets[0].target_flags = IEEE80211_MESHPREQ_TFLAGS_TO;
+ /* NB: IEEE80211_MESHPREQ_TFLAGS_USN = 0 implicitly implied */
+ IEEE80211_ADDR_COPY(preq.preq_targets[0].target_addr, rann->rann_addr);
+ preq.preq_targets[0].target_seq = rann->rann_seq;
+ /* XXX: if rootconfint have not passed, we built this preq in vain */
+ hwmp_send_preq(vap->iv_bss, vap->iv_myaddr, wh->i_addr2, &preq,
+ &hr->hr_lastrootconf, &ieee80211_hwmp_rootconfint);
+
+ /* propagate a RANN */
+ if (rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID &&
+ rann->rann_ttl > 1 &&
+ ms->ms_flags & IEEE80211_MESHFLAGS_FWD) {
hr->hr_seq = rann->rann_seq;
- if (rann->rann_ttl > 1 &&
- rann->rann_hopcount < hs->hs_maxhops &&
- (ms->ms_flags & IEEE80211_MESHFLAGS_FWD)) {
- memcpy(&prann, rann, sizeof(prann));
- prann.rann_hopcount += 1;
- prann.rann_ttl -= 1;
- prann.rann_metric += ms->ms_pmetric->mpm_metric(ni);
- hwmp_send_rann(vap->iv_bss, vap->iv_myaddr,
- broadcastaddr, &prann);
- }
+ memcpy(&prann, rann, sizeof(prann));
+ prann.rann_hopcount += 1;
+ prann.rann_ttl -= 1;
+ prann.rann_metric += ms->ms_pmetric->mpm_metric(ni);
+ hwmp_send_rann(vap->iv_bss, vap->iv_myaddr,
+ broadcastaddr, &prann);
}
}
@@ -1557,6 +1795,64 @@
#define PREQ_TFLAGS(n) preq.preq_targets[n].target_flags
#define PREQ_TADDR(n) preq.preq_targets[n].target_addr
#define PREQ_TSEQ(n) preq.preq_targets[n].target_seq
+static void
+hwmp_rediscover_cb(void *arg)
+{
+ struct ieee80211_mesh_route *rt = arg;
+ struct ieee80211vap *vap = rt->rt_vap;
+ struct ieee80211_hwmp_state *hs = vap->iv_hwmp;
+ struct ieee80211_mesh_state *ms = vap->iv_mesh;
+ struct ieee80211_hwmp_route *hr;
+ struct ieee80211_meshpreq_ie preq; /* Optimize: storing first preq? */
+
+ if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID))
+ return ; /* nothing to do */
+
+ hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route);
+ if (hr->hr_preqretries >=
+ ieee80211_hwmp_maxpreq_retries) {
+ IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
+ rt->rt_dest, NULL, "%s",
+ "no valid path , max number of discovery, send GATE");
+ /* TODO: send to known gates */
+ vap->iv_stats.is_mesh_fwd_nopath++;
+ rt->rt_flags = 0; /* Mark invalid */
+ return ; /* XXX: flush queue? */
+ }
+
+ hr->hr_preqretries++;
+
+
+ IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_HWMP, rt->rt_dest,
+ "start path rediscovery , target seq %u", hr->hr_seq);
+ /*
+ * Try to discover the path for this node.
+ * Group addressed PREQ Case A
+ */
+ preq.preq_flags = 0;
+ preq.preq_hopcount = 0;
+ preq.preq_ttl = ms->ms_ttl;
+ preq.preq_id = ++hs->hs_preqid;
+ IEEE80211_ADDR_COPY(preq.preq_origaddr, vap->iv_myaddr);
+ preq.preq_origseq = hr->hr_origseq;
+ preq.preq_lifetime = ticks_to_msecs(ieee80211_hwmp_pathtimeout);
+ preq.preq_metric = IEEE80211_MESHLMETRIC_INITIALVAL;
+ preq.preq_tcount = 1;
+ IEEE80211_ADDR_COPY(PREQ_TADDR(0), rt->rt_dest);
+ PREQ_TFLAGS(0) = 0;
+ if (ieee80211_hwmp_targetonly)
+ PREQ_TFLAGS(0) |= IEEE80211_MESHPREQ_TFLAGS_TO;
+ PREQ_TFLAGS(0) |= IEEE80211_MESHPREQ_TFLAGS_USN;
+ PREQ_TSEQ(0) = 0; /* RESERVED when USN flag is set */
+ /* XXX check return value */
+ hwmp_send_preq(vap->iv_bss, vap->iv_myaddr,
+ broadcastaddr, &preq, &hr->hr_lastpreq,
+ &ieee80211_hwmp_preqminint);
+ callout_reset(&rt->rt_discovery,
+ ieee80211_hwmp_net_diameter_traversaltime * 2,
+ hwmp_rediscover_cb, rt);
+}
+
static struct ieee80211_node *
hwmp_discover(struct ieee80211vap *vap,
const uint8_t dest[IEEE80211_ADDR_LEN], struct mbuf *m)
@@ -1591,12 +1887,29 @@
hr = IEEE80211_MESH_ROUTE_PRIV(rt,
struct ieee80211_hwmp_route);
if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0) {
+ if (hr->hr_lastdiscovery != 0 &&
+ (ticks - hr->hr_lastdiscovery <
+ (ieee80211_hwmp_net_diameter_traversaltime * 2))) {
+ IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
+ dest, NULL, "%s",
+ "too frequent discovery requeust");
+ /* XXX: stats? */
+ goto done;
+ }
+ hr->hr_lastdiscovery = ticks;
+ if (hr->hr_preqretries >=
+ ieee80211_hwmp_maxpreq_retries) {
+ IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
+ dest, NULL, "%s",
+ "no valid path , max number of discovery");
+ vap->iv_stats.is_mesh_fwd_nopath++;
+ goto done;
+ }
+ rt->rt_flags = IEEE80211_MESHRT_FLAGS_DISCOVER;
+ hr->hr_preqretries++;
if (hr->hr_origseq == 0)
hr->hr_origseq = ++hs->hs_seq;
rt->rt_metric = IEEE80211_MESHLMETRIC_INITIALVAL;
- rt->rt_lifetime =
- ticks_to_msecs(ieee80211_hwmp_pathtimeout);
- /* XXX check preq retries */
sendpreq = 1;
IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_HWMP, dest,
"start path discovery (src %s), target seq %u",
@@ -1607,26 +1920,29 @@
* Try to discover the path for this node.
* Group addressed PREQ Case A
*/
- preq.preq_flags = IEEE80211_MESHPREQ_FLAGS_AM;
+ preq.preq_flags = 0;
preq.preq_hopcount = 0;
preq.preq_ttl = ms->ms_ttl;
preq.preq_id = ++hs->hs_preqid;
IEEE80211_ADDR_COPY(preq.preq_origaddr, vap->iv_myaddr);
preq.preq_origseq = hr->hr_origseq;
- preq.preq_lifetime = rt->rt_lifetime;
- preq.preq_metric = rt->rt_metric;
+ preq.preq_lifetime =
+ ticks_to_msecs(ieee80211_hwmp_pathtimeout);
+ preq.preq_metric = IEEE80211_MESHLMETRIC_INITIALVAL;
preq.preq_tcount = 1;
IEEE80211_ADDR_COPY(PREQ_TADDR(0), dest);
PREQ_TFLAGS(0) = 0;
if (ieee80211_hwmp_targetonly)
PREQ_TFLAGS(0) |= IEEE80211_MESHPREQ_TFLAGS_TO;
- if (ieee80211_hwmp_replyforward)
- PREQ_TFLAGS(0) |= IEEE80211_MESHPREQ_TFLAGS_RF;
PREQ_TFLAGS(0) |= IEEE80211_MESHPREQ_TFLAGS_USN;
- PREQ_TSEQ(0) = hr->hr_seq;
+ PREQ_TSEQ(0) = 0; /* RESERVED when USN flag is set */
/* XXX check return value */
hwmp_send_preq(vap->iv_bss, vap->iv_myaddr,
- broadcastaddr, &preq);
+ broadcastaddr, &preq, &hr->hr_lastpreq,
+ &ieee80211_hwmp_preqminint);
+ callout_reset(&rt->rt_discovery,
+ ieee80211_hwmp_net_diameter_traversaltime * 2,
+ hwmp_rediscover_cb, rt);
}
if (rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID)
ni = ieee80211_find_txnode(vap, rt->rt_nexthop);
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/net80211/ieee80211_input.c
--- a/head/sys/net80211/ieee80211_input.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/net80211/ieee80211_input.c Wed Jul 25 16:47:10 2012 +0300
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_input.c 232484 2012-03-04 09:45:43Z glebius $");
+__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_input.c 234874 2012-05-01 15:35:10Z monthadar $");
#include "opt_wlan.h"
@@ -792,6 +792,24 @@
return EINVAL;
}
break;
+ case IEEE80211_ACTION_CAT_SELF_PROT:
+ /* If TA or RA group address discard silently */
+ if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
+ IEEE80211_IS_MULTICAST(wh->i_addr2))
+ return EINVAL;
+ /*
+ * XXX: Should we verify complete length now or it is
+ * to varying in sizes?
+ */
+ switch (ia->ia_action) {
+ case IEEE80211_ACTION_MESHPEERING_CONFIRM:
+ case IEEE80211_ACTION_MESHPEERING_CLOSE:
+ /* is not a peering candidate (yet) */
+ if (ni == vap->iv_bss)
+ return EINVAL;
+ break;
+ }
+ break;
#endif
}
return 0;
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/net80211/ieee80211_ioctl.h
--- a/head/sys/net80211/ieee80211_ioctl.h Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/net80211/ieee80211_ioctl.h Wed Jul 25 16:47:10 2012 +0300
@@ -23,7 +23,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $FreeBSD: head/sys/net80211/ieee80211_ioctl.h 234018 2012-04-08 04:51:25Z adrian $
+ * $FreeBSD: head/sys/net80211/ieee80211_ioctl.h 234894 2012-05-01 16:16:20Z monthadar $
*/
#ifndef _NET80211_IEEE80211_IOCTL_H_
#define _NET80211_IEEE80211_IOCTL_H_
@@ -339,8 +339,9 @@
struct ieee80211req_mesh_route {
uint8_t imr_flags;
-#define IEEE80211_MESHRT_FLAGS_VALID 0x01
-#define IEEE80211_MESHRT_FLAGS_PROXY 0x02
+#define IEEE80211_MESHRT_FLAGS_DISCOVER 0x01
+#define IEEE80211_MESHRT_FLAGS_VALID 0x02
+#define IEEE80211_MESHRT_FLAGS_PROXY 0x04
uint8_t imr_dest[IEEE80211_ADDR_LEN];
uint8_t imr_nexthop[IEEE80211_ADDR_LEN];
uint16_t imr_nhops;
@@ -709,6 +710,7 @@
#define IEEE80211_IOC_MESH_PR_SIG 178 /* mesh sig protocol */
#define IEEE80211_IOC_MESH_PR_CC 179 /* mesh congestion protocol */
#define IEEE80211_IOC_MESH_PR_AUTH 180 /* mesh auth protocol */
+#define IEEE80211_IOC_MESH_GATE 181 /* mesh gate XXX: 173? */
#define IEEE80211_IOC_HWMP_ROOTMODE 190 /* HWMP root mode */
#define IEEE80211_IOC_HWMP_MAXHOPS 191 /* number of hops before drop */
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/net80211/ieee80211_mesh.c
--- a/head/sys/net80211/ieee80211_mesh.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/net80211/ieee80211_mesh.c Wed Jul 25 16:47:10 2012 +0300
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
#ifdef __FreeBSD__
-__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_mesh.c 232625 2012-03-06 21:20:16Z adrian $");
+__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_mesh.c 234894 2012-05-01 16:16:20Z monthadar $");
#endif
/*
@@ -138,6 +138,10 @@
static struct ieee80211_mesh_proto_path mesh_proto_paths[4];
static struct ieee80211_mesh_proto_metric mesh_proto_metrics[4];
+#define RT_ENTRY_LOCK(rt) mtx_lock(&(rt)->rt_lock)
+#define RT_ENTRY_LOCK_ASSERT(rt) mtx_assert(&(rt)->rt_lock, MA_OWNED)
+#define RT_ENTRY_UNLOCK(rt) mtx_unlock(&(rt)->rt_lock)
+
#define MESH_RT_LOCK(ms) mtx_lock(&(ms)->ms_rt_lock)
#define MESH_RT_LOCK_ASSERT(ms) mtx_assert(&(ms)->ms_rt_lock, MA_OWNED)
#define MESH_RT_UNLOCK(ms) mtx_unlock(&(ms)->ms_rt_lock)
@@ -146,6 +150,9 @@
MALLOC_DEFINE(M_80211_MESH_PREP, "80211prep", "802.11 MESH Path Reply frame");
MALLOC_DEFINE(M_80211_MESH_PERR, "80211perr", "802.11 MESH Path Error frame");
+/* The longer one of the lifetime should be stored as new lifetime */
+#define MESH_ROUTE_LIFETIME_MAX(a, b) (a > b ? a : b)
+
MALLOC_DEFINE(M_80211_MESH_RT, "80211mesh", "802.11s routing table");
/*
@@ -168,9 +175,10 @@
}
static struct ieee80211_mesh_route *
-mesh_rt_add_locked(struct ieee80211_mesh_state *ms,
+mesh_rt_add_locked(struct ieee80211vap *vap,
const uint8_t dest[IEEE80211_ADDR_LEN])
{
+ struct ieee80211_mesh_state *ms = vap->iv_mesh;
struct ieee80211_mesh_route *rt;
KASSERT(!IEEE80211_ADDR_EQ(broadcastaddr, dest),
@@ -181,9 +189,12 @@
rt = malloc(ALIGN(sizeof(struct ieee80211_mesh_route)) +
ms->ms_ppath->mpp_privlen, M_80211_MESH_RT, M_NOWAIT | M_ZERO);
if (rt != NULL) {
+ rt->rt_vap = vap;
IEEE80211_ADDR_COPY(rt->rt_dest, dest);
rt->rt_priv = (void *)ALIGN(&rt[1]);
- rt->rt_crtime = ticks;
+ mtx_init(&rt->rt_lock, "MBSS_RT", "802.11s route entry", MTX_DEF);
+ callout_init(&rt->rt_discovery, CALLOUT_MPSAFE);
+ rt->rt_updtime = ticks; /* create time */
TAILQ_INSERT_TAIL(&ms->ms_routes, rt, rt_next);
}
return rt;
@@ -215,12 +226,56 @@
("%s: adding self to the routing table", __func__));
MESH_RT_LOCK(ms);
- rt = mesh_rt_add_locked(ms, dest);
+ rt = mesh_rt_add_locked(vap, dest);
MESH_RT_UNLOCK(ms);
return rt;
}
/*
+ * Update the route lifetime and returns the updated lifetime.
+ * If new_lifetime is zero and route is timedout it will be invalidated.
+ * new_lifetime is in msec
+ */
+int
+ieee80211_mesh_rt_update(struct ieee80211_mesh_route *rt, int new_lifetime)
+{
+ int timesince, now;
+ uint32_t lifetime = 0;
+
+ KASSERT(rt != NULL, ("route is NULL"));
+
+ now = ticks;
+ RT_ENTRY_LOCK(rt);
+
+ /* dont clobber a proxy entry gated by us */
+ if (rt->rt_flags & IEEE80211_MESHRT_FLAGS_PROXY && rt->rt_nhops == 0) {
+ RT_ENTRY_UNLOCK(rt);
+ return rt->rt_lifetime;
+ }
+
+ timesince = ticks_to_msecs(now - rt->rt_updtime);
+ rt->rt_updtime = now;
+ if (timesince >= rt->rt_lifetime) {
+ if (new_lifetime != 0) {
+ rt->rt_lifetime = new_lifetime;
+ }
+ else {
+ rt->rt_flags &= ~IEEE80211_MESHRT_FLAGS_VALID;
+ rt->rt_lifetime = 0;
+ }
+ } else {
+ /* update what is left of lifetime */
+ rt->rt_lifetime = rt->rt_lifetime - timesince;
+ rt->rt_lifetime = MESH_ROUTE_LIFETIME_MAX(
+ new_lifetime, rt->rt_lifetime);
+ }
+ lifetime = rt->rt_lifetime;
+ RT_ENTRY_UNLOCK(rt);
+
+ return lifetime;
+}
+
+/*
* Add a proxy route (as needed) for the specified destination.
*/
void
@@ -233,7 +288,7 @@
MESH_RT_LOCK(ms);
rt = mesh_rt_find_locked(ms, dest);
if (rt == NULL) {
- rt = mesh_rt_add_locked(ms, dest);
+ rt = mesh_rt_add_locked(vap, dest);
if (rt == NULL) {
IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, dest,
"%s", "unable to add proxy entry");
@@ -241,12 +296,14 @@
} else {
IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, dest,
"%s", "add proxy entry");
+ IEEE80211_ADDR_COPY(rt->rt_mesh_gate, vap->iv_myaddr);
IEEE80211_ADDR_COPY(rt->rt_nexthop, vap->iv_myaddr);
rt->rt_flags |= IEEE80211_MESHRT_FLAGS_VALID
| IEEE80211_MESHRT_FLAGS_PROXY;
}
- /* XXX assert PROXY? */
} else if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0) {
+ KASSERT(rt->rt_flags & IEEE80211_MESHRT_FLAGS_PROXY,
+ ("no proxy flag for poxy entry"));
struct ieee80211com *ic = vap->iv_ic;
/*
* Fix existing entry created by received frames from
@@ -271,6 +328,13 @@
mesh_rt_del(struct ieee80211_mesh_state *ms, struct ieee80211_mesh_route *rt)
{
TAILQ_REMOVE(&ms->ms_routes, rt, rt_next);
+ /*
+ * Grab the lock before destroying it, to be sure no one else
+ * is holding the route.
+ */
+ RT_ENTRY_LOCK(rt);
+ callout_drain(&rt->rt_discovery);
+ mtx_destroy(&rt->rt_lock);
free(rt, M_80211_MESH_RT);
}
@@ -284,6 +348,13 @@
MESH_RT_LOCK(ms);
TAILQ_FOREACH_SAFE(rt, &ms->ms_routes, rt_next, next) {
if (IEEE80211_ADDR_EQ(rt->rt_dest, dest)) {
+ if (rt->rt_flags & IEEE80211_MESHRT_FLAGS_PROXY) {
+ ms->ms_ppath->mpp_senderror(vap, dest, rt,
+ IEEE80211_REASON_MESH_PERR_NO_PROXY);
+ } else {
+ ms->ms_ppath->mpp_senderror(vap, dest, rt,
+ IEEE80211_REASON_MESH_PERR_DEST_UNREACH);
+ }
mesh_rt_del(ms, rt);
MESH_RT_UNLOCK(ms);
return;
@@ -335,8 +406,11 @@
return;
MESH_RT_LOCK(ms);
TAILQ_FOREACH_SAFE(rt, &ms->ms_routes, rt_next, next) {
- if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0 &&
- ticks - rt->rt_crtime >= ms->ms_ppath->mpp_inact)
+ /* Discover paths will be deleted by their own callout */
+ if (rt->rt_flags & IEEE80211_MESHRT_FLAGS_DISCOVER)
+ continue;
+ ieee80211_mesh_rt_update(rt, 0);
+ if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0)
mesh_rt_del(ms, rt);
}
MESH_RT_UNLOCK(ms);
@@ -430,25 +504,25 @@
/*
* Register action frame handlers.
*/
- ieee80211_recv_action_register(IEEE80211_ACTION_CAT_MESHPEERING,
+ ieee80211_recv_action_register(IEEE80211_ACTION_CAT_SELF_PROT,
IEEE80211_ACTION_MESHPEERING_OPEN,
mesh_recv_action_meshpeering_open);
- ieee80211_recv_action_register(IEEE80211_ACTION_CAT_MESHPEERING,
+ ieee80211_recv_action_register(IEEE80211_ACTION_CAT_SELF_PROT,
IEEE80211_ACTION_MESHPEERING_CONFIRM,
mesh_recv_action_meshpeering_confirm);
- ieee80211_recv_action_register(IEEE80211_ACTION_CAT_MESHPEERING,
+ ieee80211_recv_action_register(IEEE80211_ACTION_CAT_SELF_PROT,
IEEE80211_ACTION_MESHPEERING_CLOSE,
mesh_recv_action_meshpeering_close);
ieee80211_recv_action_register(IEEE80211_ACTION_CAT_MESH,
IEEE80211_ACTION_MESH_LMETRIC, mesh_recv_action_meshlmetric);
- ieee80211_send_action_register(IEEE80211_ACTION_CAT_MESHPEERING,
+ ieee80211_send_action_register(IEEE80211_ACTION_CAT_SELF_PROT,
IEEE80211_ACTION_MESHPEERING_OPEN,
mesh_send_action_meshpeering_open);
- ieee80211_send_action_register(IEEE80211_ACTION_CAT_MESHPEERING,
+ ieee80211_send_action_register(IEEE80211_ACTION_CAT_SELF_PROT,
IEEE80211_ACTION_MESHPEERING_CONFIRM,
mesh_send_action_meshpeering_confirm);
- ieee80211_send_action_register(IEEE80211_ACTION_CAT_MESHPEERING,
+ ieee80211_send_action_register(IEEE80211_ACTION_CAT_SELF_PROT,
IEEE80211_ACTION_MESHPEERING_CLOSE,
mesh_send_action_meshpeering_close);
ieee80211_send_action_register(IEEE80211_ACTION_CAT_MESH,
@@ -485,7 +559,7 @@
args[1] = ni->ni_mllid;
args[2] = IEEE80211_REASON_PEER_LINK_CANCELED;
ieee80211_send_action(ni,
- IEEE80211_ACTION_CAT_MESHPEERING,
+ IEEE80211_ACTION_CAT_SELF_PROT,
IEEE80211_ACTION_MESHPEERING_CLOSE,
args);
}
@@ -856,9 +930,14 @@
struct ieee80211_node *ni;
int err;
- if (mc->mc_ttl == 0) {
+ /*
+ * mesh ttl of 1 means we are the last one receving it,
+ * according to amendment we decrement and then check if
+ * 0, if so we dont forward.
+ */
+ if (mc->mc_ttl < 1) {
IEEE80211_NOTE_FRAME(vap, IEEE80211_MSG_MESH, wh,
- "%s", "frame not fwd'd, ttl 0");
+ "%s", "frame not fwd'd, ttl 1");
vap->iv_stats.is_mesh_fwd_ttl++;
return;
}
@@ -898,8 +977,16 @@
} else {
ni = mesh_find_txnode(vap, whcopy->i_addr3);
if (ni == NULL) {
+ /*
+ * [Optional] any of the following three actions:
+ * o silently discard
+ * o trigger a path discovery
+ * o inform TA that meshDA is unknown.
+ */
IEEE80211_NOTE_FRAME(vap, IEEE80211_MSG_MESH, wh,
"%s", "frame not fwd'd, no path");
+ ms->ms_ppath->mpp_senderror(vap, whcopy->i_addr3, NULL,
+ IEEE80211_REASON_MESH_PERR_NO_FI);
vap->iv_stats.is_mesh_fwd_nopath++;
m_freem(mcopy);
return;
@@ -926,9 +1013,10 @@
static struct mbuf *
mesh_decap(struct ieee80211vap *vap, struct mbuf *m, int hdrlen, int meshdrlen)
{
-#define WHDIR(wh) ((wh)->i_fc[1] & IEEE80211_FC1_DIR_MASK)
+#define WHDIR(wh) ((wh)->i_fc[1] & IEEE80211_FC1_DIR_MASK)
+#define MC01(mc) ((const struct ieee80211_meshcntl_ae01 *)mc)
uint8_t b[sizeof(struct ieee80211_qosframe_addr4) +
- sizeof(struct ieee80211_meshcntl_ae11)];
+ sizeof(struct ieee80211_meshcntl_ae10)];
const struct ieee80211_qosframe_addr4 *wh;
const struct ieee80211_meshcntl_ae10 *mc;
struct ether_header *eh;
@@ -962,13 +1050,14 @@
m_adj(m, hdrlen - sizeof(*eh));
}
eh = mtod(m, struct ether_header *);
- ae = mc->mc_flags & 3;
+ ae = mc->mc_flags & IEEE80211_MESH_AE_MASK;
if (WHDIR(wh) == IEEE80211_FC1_DIR_FROMDS) {
IEEE80211_ADDR_COPY(eh->ether_dhost, wh->i_addr1);
- if (ae == 0) {
+ if (ae == IEEE80211_MESH_AE_00) {
IEEE80211_ADDR_COPY(eh->ether_shost, wh->i_addr3);
- } else if (ae == 1) {
- IEEE80211_ADDR_COPY(eh->ether_shost, mc->mc_addr4);
+ } else if (ae == IEEE80211_MESH_AE_01) {
+ IEEE80211_ADDR_COPY(eh->ether_shost,
+ MC01(mc)->mc_addr4);
} else {
IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY,
(const struct ieee80211_frame *)wh, NULL,
@@ -978,12 +1067,12 @@
return NULL;
}
} else {
- if (ae == 0) {
+ if (ae == IEEE80211_MESH_AE_00) {
IEEE80211_ADDR_COPY(eh->ether_dhost, wh->i_addr3);
IEEE80211_ADDR_COPY(eh->ether_shost, wh->i_addr4);
- } else if (ae == 2) {
- IEEE80211_ADDR_COPY(eh->ether_dhost, mc->mc_addr4);
- IEEE80211_ADDR_COPY(eh->ether_shost, mc->mc_addr5);
+ } else if (ae == IEEE80211_MESH_AE_10) {
+ IEEE80211_ADDR_COPY(eh->ether_dhost, mc->mc_addr5);
+ IEEE80211_ADDR_COPY(eh->ether_shost, mc->mc_addr6);
} else {
IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY,
(const struct ieee80211_frame *)wh, NULL,
@@ -1005,7 +1094,8 @@
eh->ether_type = htons(m->m_pkthdr.len - sizeof(*eh));
}
return m;
-#undef WDIR
+#undef WDIR
+#undef MC01
}
/*
@@ -1021,12 +1111,13 @@
KASSERT((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS,
("bad dir 0x%x:0x%x", wh->i_fc[0], wh->i_fc[1]));
- KASSERT(ae == 0 || ae == 2, ("bad AE %d", ae));
- if (ae == 2) { /* ucast w/ proxy */
+ KASSERT(ae == IEEE80211_MESH_AE_00 || ae == IEEE80211_MESH_AE_10,
+ ("bad AE %d", ae));
+ if (ae == IEEE80211_MESH_AE_10) { /* ucast w/ proxy */
const struct ieee80211_meshcntl_ae10 *mc10 =
(const struct ieee80211_meshcntl_ae10 *) mc;
struct ieee80211_mesh_route *rt =
- ieee80211_mesh_rt_find(vap, mc10->mc_addr4);
+ ieee80211_mesh_rt_find(vap, mc10->mc_addr5);
/* check for proxy route to ourself */
return (rt != NULL &&
(rt->rt_flags & IEEE80211_MESHRT_FLAGS_PROXY));
@@ -1034,19 +1125,172 @@
return IEEE80211_ADDR_EQ(wh->i_addr3, vap->iv_myaddr);
}
+/*
+ * Verifies transmitter, updates lifetime, precursor list and forwards data.
+ * > 0 means we have forwarded data and no need to process locally
+ * == 0 means we want to process locally (and we may have forwarded data
+ * < 0 means there was an error and data should be discarded
+ */
+static int
+mesh_recv_indiv_data_to_fwrd(struct ieee80211vap *vap, struct mbuf *m,
+ struct ieee80211_frame *wh, const struct ieee80211_meshcntl *mc)
+{
+ struct ieee80211_qosframe_addr4 *qwh;
+ struct ieee80211_mesh_state *ms = vap->iv_mesh;
+ struct ieee80211_mesh_route *rt_meshda, *rt_meshsa;
+
+ qwh = (struct ieee80211_qosframe_addr4 *)wh;
+
+ /*
+ * TODO:
+ * o verify addr2 is a legitimate transmitter
+ * o lifetime of precursor of addr3 (addr2) is max(init, curr)
+ * o lifetime of precursor of addr4 (nexthop) is max(init, curr)
+ */
+
+ /* set lifetime of addr3 (meshDA) to initial value */
+ rt_meshda = ieee80211_mesh_rt_find(vap, qwh->i_addr3);
+ if (rt_meshda == NULL) {
+ IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, qwh->i_addr2,
+ "no route to meshDA(%6D)", qwh->i_addr3, ":");
+ /*
+ * [Optional] any of the following three actions:
+ * o silently discard [X]
+ * o trigger a path discovery [ ]
+ * o inform TA that meshDA is unknown. [ ]
+ */
+ /* XXX: stats */
+ return (-1);
+ }
+
+ ieee80211_mesh_rt_update(rt_meshda, ticks_to_msecs(
+ ms->ms_ppath->mpp_inact));
+
+ /* set lifetime of addr4 (meshSA) to initial value */
+ rt_meshsa = ieee80211_mesh_rt_find(vap, qwh->i_addr4);
+ KASSERT(rt_meshsa != NULL, ("no route"));
+ ieee80211_mesh_rt_update(rt_meshsa, ticks_to_msecs(
+ ms->ms_ppath->mpp_inact));
+
+ mesh_forward(vap, m, mc);
+ return (1); /* dont process locally */
+}
+
+/*
+ * Verifies transmitter, updates lifetime, precursor list and process data
+ * locally, if data is is proxy with AE = 10 it could mean data should go
+ * on another mesh path or data should be forwarded to the DS.
+ *
+ * > 0 means we have forwarded data and no need to process locally
+ * == 0 means we want to process locally (and we may have forwarded data
+ * < 0 means there was an error and data should be discarded
+ */
+static int
+mesh_recv_indiv_data_to_me(struct ieee80211vap *vap, struct mbuf *m,
+ struct ieee80211_frame *wh, const struct ieee80211_meshcntl *mc)
+{
+ struct ieee80211_qosframe_addr4 *qwh;
+ const struct ieee80211_meshcntl_ae10 *mc10;
+ struct ieee80211_mesh_state *ms = vap->iv_mesh;
+ struct ieee80211_mesh_route *rt;
+ int ae;
+
+ qwh = (struct ieee80211_qosframe_addr4 *)wh;
+ mc10 = (const struct ieee80211_meshcntl_ae10 *)mc;
+
+ /*
+ * TODO:
+ * o verify addr2 is a legitimate transmitter
+ * o lifetime of precursor entry is max(init, curr)
+ */
+
+ /* set lifetime of addr4 (meshSA) to initial value */
+ rt = ieee80211_mesh_rt_find(vap, qwh->i_addr4);
+ KASSERT(rt != NULL, ("no route"));
+ ieee80211_mesh_rt_update(rt, ticks_to_msecs(ms->ms_ppath->mpp_inact));
+ rt = NULL;
+
+ ae = mc10->mc_flags & IEEE80211_MESH_AE_MASK;
+ KASSERT(ae == IEEE80211_MESH_AE_00 ||
+ ae == IEEE80211_MESH_AE_10, ("bad AE %d", ae));
+ if (ae == IEEE80211_MESH_AE_10) {
+ if (IEEE80211_ADDR_EQ(mc10->mc_addr5, qwh->i_addr3)) {
+ return (0); /* process locally */
+ }
+
+ rt = ieee80211_mesh_rt_find(vap, mc10->mc_addr5);
+ if (rt != NULL &&
+ (rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) &&
+ (rt->rt_flags & IEEE80211_MESHRT_FLAGS_PROXY) == 0) {
+ /*
+ * Forward on another mesh-path, according to
+ * amendment as specified in 9.32.4.1
+ */
+ IEEE80211_ADDR_COPY(qwh->i_addr3, mc10->mc_addr5);
+ mesh_forward(vap, m,
+ (const struct ieee80211_meshcntl *)mc10);
+ return (1); /* dont process locally */
+ }
+ /*
+ * All other cases: forward of MSDUs from the MBSS to DS indiv.
+ * addressed according to 13.11.3.2.
+ */
+ }
+ return (0); /* process locally */
+}
+
+/*
+ * Try to forward the group addressed data on to other mesh STAs, and
+ * also to the DS.
+ *
+ * > 0 means we have forwarded data and no need to process locally
+ * == 0 means we want to process locally (and we may have forwarded data
+ * < 0 means there was an error and data should be discarded
+ */
+static int
+mesh_recv_group_data(struct ieee80211vap *vap, struct mbuf *m,
+ struct ieee80211_frame *wh, const struct ieee80211_meshcntl *mc)
+{
+#define MC01(mc) ((const struct ieee80211_meshcntl_ae01 *)mc)
+ struct ieee80211_mesh_state *ms = vap->iv_mesh;
+
+ mesh_forward(vap, m, mc);
+
+ if(mc->mc_ttl > 0) {
+ if (mc->mc_flags & IEEE80211_MESH_AE_01) {
+ /*
+ * Forward of MSDUs from the MBSS to DS group addressed
+ * (according to 13.11.3.2)
+ * This happens by delivering the packet, and a bridge
+ * will sent it on another port member.
+ */
+ if (ms->ms_flags & IEEE80211_MESHFLAGS_GATE &&
+ ms->ms_flags & IEEE80211_MESHFLAGS_FWD)
+ IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH,
+ MC01(mc)->mc_addr4, "%s",
+ "forward from MBSS to the DS");
+ }
+ }
+ return (0); /* process locally */
+#undef MC01
+}
+
static int
mesh_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf)
{
#define HAS_SEQ(type) ((type & 0x4) == 0)
+#define MC01(mc) ((const struct ieee80211_meshcntl_ae01 *)mc)
+#define MC10(mc) ((const struct ieee80211_meshcntl_ae10 *)mc)
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211com *ic = ni->ni_ic;
struct ifnet *ifp = vap->iv_ifp;
struct ieee80211_frame *wh;
const struct ieee80211_meshcntl *mc;
- int hdrspace, meshdrlen, need_tap;
- uint8_t dir, type, subtype;
+ int hdrspace, meshdrlen, need_tap, error;
+ uint8_t dir, type, subtype, ae;
uint32_t seq;
- uint8_t *addr, qos[2];
+ const uint8_t *addr;
+ uint8_t qos[2];
ieee80211_seq rxseq;
KASSERT(ni != NULL, ("null node"));
@@ -1135,7 +1379,7 @@
ni->ni_mlstate);
vap->iv_stats.is_mesh_nolink++;
goto out;
- }
+ }
if (dir != IEEE80211_FC1_DIR_FROMDS &&
dir != IEEE80211_FC1_DIR_DSTODS) {
IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
@@ -1217,12 +1461,28 @@
*/
mc = (const struct ieee80211_meshcntl *)
(mtod(m, const uint8_t *) + hdrspace);
+ ae = mc->mc_flags & IEEE80211_MESH_AE_MASK;
meshdrlen = sizeof(struct ieee80211_meshcntl) +
- (mc->mc_flags & 3) * IEEE80211_ADDR_LEN;
+ ae * IEEE80211_ADDR_LEN;
hdrspace += meshdrlen;
+
+ /* pull complete hdrspace = ieee80211_hdrspace + meshcontrol */
+ if ((meshdrlen > sizeof(struct ieee80211_meshcntl)) &&
+ (m->m_len < hdrspace) &&
+ ((m = m_pullup(m, hdrspace)) == NULL)) {
+ IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
+ ni->ni_macaddr, NULL,
+ "data too short: expecting %u", hdrspace);
+ vap->iv_stats.is_rx_tooshort++;
+ goto out; /* XXX */
+ }
+ /* XXX: are we sure there is no reallocating after m_pullup? */
+
seq = LE_READ_4(mc->mc_seq);
if (IEEE80211_IS_MULTICAST(wh->i_addr1))
addr = wh->i_addr3;
+ else if (ae == IEEE80211_MESH_AE_01)
+ addr = MC01(mc)->mc_addr4;
else
addr = ((struct ieee80211_qosframe_addr4 *)wh)->i_addr4;
if (IEEE80211_ADDR_EQ(vap->iv_myaddr, addr)) {
@@ -1236,17 +1496,22 @@
goto out;
}
- /*
- * Potentially forward packet. See table s36 (p140)
- * for the rules. XXX tap fwd'd packets not for us?
- */
- if (dir == IEEE80211_FC1_DIR_FROMDS ||
- !mesh_isucastforme(vap, wh, mc)) {
- mesh_forward(vap, m, mc);
- if (dir == IEEE80211_FC1_DIR_DSTODS)
- goto out;
- /* NB: fall thru to deliver mcast frames locally */
- }
+ /* This code "routes" the frame to the right control path */
+ if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
+ if (IEEE80211_ADDR_EQ(vap->iv_myaddr, wh->i_addr3))
+ error =
+ mesh_recv_indiv_data_to_me(vap, m, wh, mc);
+ else if (IEEE80211_IS_MULTICAST(wh->i_addr3))
+ error = mesh_recv_group_data(vap, m, wh, mc);
+ else
+ error = mesh_recv_indiv_data_to_fwrd(vap, m,
+ wh, mc);
+ } else
+ error = mesh_recv_group_data(vap, m, wh, mc);
+ if (error < 0)
+ goto err;
+ else if (error > 0)
+ goto out;
if (ieee80211_radiotap_active_vap(vap))
ieee80211_radiotap_rx(vap, m);
@@ -1328,6 +1593,9 @@
m_freem(m);
}
return type;
+#undef HAS_SEQ
+#undef MC01
+#undef MC10
}
static void
@@ -1338,6 +1606,7 @@
struct ieee80211_mesh_state *ms = vap->iv_mesh;
struct ieee80211com *ic = ni->ni_ic;
struct ieee80211_frame *wh;
+ struct ieee80211_mesh_route *rt;
uint8_t *frm, *efrm;
wh = mtod(m0, struct ieee80211_frame *);
@@ -1430,20 +1699,41 @@
* XXX backoff on repeated failure
*/
if (ni != vap->iv_bss &&
- (ms->ms_flags & IEEE80211_MESHFLAGS_AP) &&
- ni->ni_mlstate == IEEE80211_NODE_MESH_IDLE) {
- uint16_t args[1];
+ (ms->ms_flags & IEEE80211_MESHFLAGS_AP)) {
+ switch (ni->ni_mlstate) {
+ case IEEE80211_NODE_MESH_IDLE:
+ {
+ uint16_t args[1];
- ni->ni_mlpid = mesh_generateid(vap);
- if (ni->ni_mlpid == 0)
- return;
- mesh_linkchange(ni, IEEE80211_NODE_MESH_OPENSNT);
- args[0] = ni->ni_mlpid;
- ieee80211_send_action(ni,
- IEEE80211_ACTION_CAT_MESHPEERING,
- IEEE80211_ACTION_MESHPEERING_OPEN, args);
- ni->ni_mlrcnt = 0;
- mesh_peer_timeout_setup(ni);
+ ni->ni_mlpid = mesh_generateid(vap);
+ if (ni->ni_mlpid == 0)
+ return;
+ mesh_linkchange(ni, IEEE80211_NODE_MESH_OPENSNT);
+ args[0] = ni->ni_mlpid;
+ ieee80211_send_action(ni,
+ IEEE80211_ACTION_CAT_SELF_PROT,
+ IEEE80211_ACTION_MESHPEERING_OPEN, args);
+ ni->ni_mlrcnt = 0;
+ mesh_peer_timeout_setup(ni);
+ break;
+ }
+ case IEEE80211_NODE_MESH_ESTABLISHED:
+ {
+ /*
+ * Valid beacon from a peer mesh STA
+ * bump TA lifetime
+ */
+ rt = ieee80211_mesh_rt_find(vap, wh->i_addr2);
+ if(rt != NULL) {
+ ieee80211_mesh_rt_update(rt,
+ ticks_to_msecs(
+ ms->ms_ppath->mpp_inact));
+ }
+ break;
+ }
+ default:
+ break; /* ignore */
+ }
}
break;
}
@@ -1573,8 +1863,7 @@
}
/*
- * Parse meshpeering action ie's for open+confirm frames; the
- * important bits are returned in the supplied structure.
+ * Parse meshpeering action ie's for MPM frames
*/
static const struct ieee80211_meshpeer_ie *
mesh_parse_meshpeering_action(struct ieee80211_node *ni,
@@ -1584,7 +1873,9 @@
{
struct ieee80211vap *vap = ni->ni_vap;
const struct ieee80211_meshpeer_ie *mpie;
+ uint16_t args[3];
const uint8_t *meshid, *meshconf, *meshpeer;
+ uint8_t sendclose = 0; /* 1 = MPM frame rejected, close will be sent */
meshid = meshconf = meshpeer = NULL;
while (efrm - frm > 1) {
@@ -1600,15 +1891,28 @@
meshpeer = frm;
mpie = (const struct ieee80211_meshpeer_ie *) frm;
memset(mp, 0, sizeof(*mp));
+ mp->peer_len = mpie->peer_len;
+ mp->peer_proto = LE_READ_2(&mpie->peer_proto);
mp->peer_llinkid = LE_READ_2(&mpie->peer_llinkid);
- /* NB: peer link ID is optional on these frames */
- if (subtype == IEEE80211_MESH_PEER_LINK_CLOSE &&
- mpie->peer_len == 8) {
- mp->peer_linkid = 0;
- mp->peer_rcode = LE_READ_2(&mpie->peer_linkid);
- } else {
- mp->peer_linkid = LE_READ_2(&mpie->peer_linkid);
- mp->peer_rcode = LE_READ_2(&mpie->peer_rcode);
+ switch (subtype) {
+ case IEEE80211_ACTION_MESHPEERING_CONFIRM:
+ mp->peer_linkid =
+ LE_READ_2(&mpie->peer_linkid);
+ break;
+ case IEEE80211_ACTION_MESHPEERING_CLOSE:
+ /* NB: peer link ID is optional */
+ if (mpie->peer_len ==
+ (IEEE80211_MPM_BASE_SZ + 2)) {
+ mp->peer_linkid = 0;
+ mp->peer_rcode =
+ LE_READ_2(&mpie->peer_linkid);
+ } else {
+ mp->peer_linkid =
+ LE_READ_2(&mpie->peer_linkid);
+ mp->peer_rcode =
+ LE_READ_2(&mpie->peer_rcode);
+ }
+ break;
}
break;
}
@@ -1616,22 +1920,46 @@
}
/*
- * Verify the contents of the frame. Action frames with
- * close subtype don't have a Mesh Configuration IE.
- * If if fails validation, close the peer link.
+ * Verify the contents of the frame.
+ * If it fails validation, close the peer link.
*/
- KASSERT(meshpeer != NULL &&
- subtype != IEEE80211_ACTION_MESHPEERING_CLOSE,
- ("parsing close action"));
+ if (mesh_verify_meshpeer(vap, subtype, (const uint8_t *)mp)) {
+ sendclose = 1;
+ IEEE80211_DISCARD(vap,
+ IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH,
+ wh, NULL, "%s", "MPM validation failed");
+ }
- if (mesh_verify_meshid(vap, meshid) ||
- mesh_verify_meshpeer(vap, subtype, meshpeer) ||
- mesh_verify_meshconf(vap, meshconf)) {
- uint16_t args[3];
-
+ /* If meshid is not the same reject any frames type. */
+ if (sendclose == 0 && mesh_verify_meshid(vap, meshid)) {
+ sendclose = 1;
IEEE80211_DISCARD(vap,
IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH,
wh, NULL, "%s", "not for our mesh");
+ if (subtype == IEEE80211_ACTION_MESHPEERING_CLOSE) {
+ /*
+ * Standard not clear about this, if we dont ignore
+ * there will be an endless loop between nodes sending
+ * CLOSE frames between each other with wrong meshid.
+ * Discard and timers will bring FSM to IDLE state.
+ */
+ return NULL;
+ }
+ }
+
+ /*
+ * Close frames are accepted if meshid is the same.
+ * Verify the other two types.
+ */
+ if (sendclose == 0 && subtype != IEEE80211_ACTION_MESHPEERING_CLOSE &&
+ mesh_verify_meshconf(vap, meshconf)) {
+ sendclose = 1;
+ IEEE80211_DISCARD(vap,
+ IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH,
+ wh, NULL, "%s", "configuration missmatch");
+ }
+
+ if (sendclose) {
vap->iv_stats.is_rx_mgtdiscard++;
switch (ni->ni_mlstate) {
case IEEE80211_NODE_MESH_IDLE:
@@ -1644,9 +1972,17 @@
case IEEE80211_NODE_MESH_CONFIRMRCV:
args[0] = ni->ni_mlpid;
args[1] = ni->ni_mllid;
- args[2] = IEEE80211_REASON_PEER_LINK_CANCELED;
+ /* Reason codes for rejection */
+ switch (subtype) {
+ case IEEE80211_ACTION_MESHPEERING_OPEN:
+ args[2] = IEEE80211_REASON_MESH_CPVIOLATION;
+ break;
+ case IEEE80211_ACTION_MESHPEERING_CONFIRM:
+ args[2] = IEEE80211_REASON_MESH_INCONS_PARAMS;
+ break;
+ }
ieee80211_send_action(ni,
- IEEE80211_ACTION_CAT_MESHPEERING,
+ IEEE80211_ACTION_CAT_SELF_PROT,
IEEE80211_ACTION_MESHPEERING_CLOSE,
args);
mesh_linkchange(ni, IEEE80211_NODE_MESH_HOLDING);
@@ -1655,6 +1991,7 @@
}
return NULL;
}
+
return (const struct ieee80211_meshpeer_ie *) mp;
}
@@ -1664,6 +2001,7 @@
const uint8_t *frm, const uint8_t *efrm)
{
struct ieee80211vap *vap = ni->ni_vap;
+ struct ieee80211_mesh_state *ms = vap->iv_mesh;
struct ieee80211_meshpeer_ie ie;
const struct ieee80211_meshpeer_ie *meshpeer;
uint16_t args[3];
@@ -1681,6 +2019,19 @@
switch (ni->ni_mlstate) {
case IEEE80211_NODE_MESH_IDLE:
+ /* Reject open request if reached our maximum neighbor count */
+ if (ms->ms_neighbors >= IEEE80211_MESH_MAX_NEIGHBORS) {
+ args[0] = meshpeer->peer_llinkid;
+ args[1] = 0;
+ args[2] = IEEE80211_REASON_MESH_MAX_PEERS;
+ ieee80211_send_action(ni,
+ IEEE80211_ACTION_CAT_SELF_PROT,
+ IEEE80211_ACTION_MESHPEERING_CLOSE,
+ args);
+ /* stay in IDLE state */
+ return (0);
+ }
+ /* Open frame accepted */
mesh_linkchange(ni, IEEE80211_NODE_MESH_OPENRCV);
ni->ni_mllid = meshpeer->peer_llinkid;
ni->ni_mlpid = mesh_generateid(vap);
@@ -1689,13 +2040,13 @@
args[0] = ni->ni_mlpid;
/* Announce we're open too... */
ieee80211_send_action(ni,
- IEEE80211_ACTION_CAT_MESHPEERING,
+ IEEE80211_ACTION_CAT_SELF_PROT,
IEEE80211_ACTION_MESHPEERING_OPEN, args);
/* ...and confirm the link. */
args[0] = ni->ni_mlpid;
args[1] = ni->ni_mllid;
ieee80211_send_action(ni,
- IEEE80211_ACTION_CAT_MESHPEERING,
+ IEEE80211_ACTION_CAT_SELF_PROT,
IEEE80211_ACTION_MESHPEERING_CONFIRM,
args);
mesh_peer_timeout_setup(ni);
@@ -1707,7 +2058,7 @@
args[1] = ni->ni_mlpid;
args[2] = IEEE80211_REASON_PEER_LINK_CANCELED;
ieee80211_send_action(ni,
- IEEE80211_ACTION_CAT_MESHPEERING,
+ IEEE80211_ACTION_CAT_SELF_PROT,
IEEE80211_ACTION_MESHPEERING_CLOSE,
args);
mesh_linkchange(ni, IEEE80211_NODE_MESH_HOLDING);
@@ -1718,7 +2069,7 @@
args[0] = ni->ni_mlpid;
args[1] = ni->ni_mllid;
ieee80211_send_action(ni,
- IEEE80211_ACTION_CAT_MESHPEERING,
+ IEEE80211_ACTION_CAT_SELF_PROT,
IEEE80211_ACTION_MESHPEERING_CONFIRM,
args);
break;
@@ -1728,7 +2079,7 @@
args[0] = ni->ni_mlpid;
args[1] = ni->ni_mllid;
ieee80211_send_action(ni,
- IEEE80211_ACTION_CAT_MESHPEERING,
+ IEEE80211_ACTION_CAT_SELF_PROT,
IEEE80211_ACTION_MESHPEERING_CONFIRM,
args);
/* NB: don't setup/clear any timeout */
@@ -1740,7 +2091,7 @@
args[1] = ni->ni_mllid;
args[2] = IEEE80211_REASON_PEER_LINK_CANCELED;
ieee80211_send_action(ni,
- IEEE80211_ACTION_CAT_MESHPEERING,
+ IEEE80211_ACTION_CAT_SELF_PROT,
IEEE80211_ACTION_MESHPEERING_CLOSE,
args);
mesh_linkchange(ni,
@@ -1753,7 +2104,7 @@
args[0] = ni->ni_mlpid;
args[1] = ni->ni_mllid;
ieee80211_send_action(ni,
- IEEE80211_ACTION_CAT_MESHPEERING,
+ IEEE80211_ACTION_CAT_SELF_PROT,
IEEE80211_ACTION_MESHPEERING_CONFIRM,
args);
mesh_peer_timeout_stop(ni);
@@ -1764,7 +2115,7 @@
args[1] = ni->ni_mlpid;
args[2] = IEEE80211_REASON_PEER_LINK_CANCELED;
ieee80211_send_action(ni,
- IEEE80211_ACTION_CAT_MESHPEERING,
+ IEEE80211_ACTION_CAT_SELF_PROT,
IEEE80211_ACTION_MESHPEERING_CLOSE,
args);
mesh_linkchange(ni, IEEE80211_NODE_MESH_HOLDING);
@@ -1774,16 +2125,17 @@
args[0] = ni->ni_mlpid;
args[1] = ni->ni_mllid;
ieee80211_send_action(ni,
- IEEE80211_ACTION_CAT_MESHPEERING,
+ IEEE80211_ACTION_CAT_SELF_PROT,
IEEE80211_ACTION_MESHPEERING_CONFIRM,
args);
break;
case IEEE80211_NODE_MESH_HOLDING:
args[0] = ni->ni_mlpid;
args[1] = meshpeer->peer_llinkid;
- args[2] = IEEE80211_REASON_MESH_MAX_RETRIES;
+ /* Standard not clear about what the reaason code should be */
+ args[2] = IEEE80211_REASON_PEER_LINK_CANCELED;
ieee80211_send_action(ni,
- IEEE80211_ACTION_CAT_MESHPEERING,
+ IEEE80211_ACTION_CAT_SELF_PROT,
IEEE80211_ACTION_MESHPEERING_CLOSE,
args);
break;
@@ -1819,13 +2171,15 @@
break;
case IEEE80211_NODE_MESH_OPENSNT:
mesh_linkchange(ni, IEEE80211_NODE_MESH_CONFIRMRCV);
+ mesh_peer_timeout_setup(ni);
break;
case IEEE80211_NODE_MESH_HOLDING:
args[0] = ni->ni_mlpid;
args[1] = meshpeer->peer_llinkid;
- args[2] = IEEE80211_REASON_MESH_MAX_RETRIES;
+ /* Standard not clear about what the reaason code should be */
+ args[2] = IEEE80211_REASON_PEER_LINK_CANCELED;
ieee80211_send_action(ni,
- IEEE80211_ACTION_CAT_MESHPEERING,
+ IEEE80211_ACTION_CAT_SELF_PROT,
IEEE80211_ACTION_MESHPEERING_CLOSE,
args);
break;
@@ -1835,7 +2189,7 @@
args[1] = ni->ni_mllid;
args[2] = IEEE80211_REASON_PEER_LINK_CANCELED;
ieee80211_send_action(ni,
- IEEE80211_ACTION_CAT_MESHPEERING,
+ IEEE80211_ACTION_CAT_SELF_PROT,
IEEE80211_ACTION_MESHPEERING_CLOSE,
args);
mesh_linkchange(ni, IEEE80211_NODE_MESH_HOLDING);
@@ -1858,8 +2212,23 @@
const struct ieee80211_frame *wh,
const uint8_t *frm, const uint8_t *efrm)
{
+ struct ieee80211_meshpeer_ie ie;
+ const struct ieee80211_meshpeer_ie *meshpeer;
uint16_t args[3];
+ /* +2 for action + code */
+ meshpeer = mesh_parse_meshpeering_action(ni, wh, frm+2, efrm, &ie,
+ IEEE80211_ACTION_MESHPEERING_CLOSE);
+ if (meshpeer == NULL) {
+ return 0;
+ }
+
+ /*
+ * XXX: check reason code, for example we could receive
+ * IEEE80211_REASON_MESH_MAX_PEERS then we should not attempt
+ * to peer again.
+ */
+
IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH,
ni, "%s", "recv PEER CLOSE");
@@ -1875,7 +2244,7 @@
args[1] = ni->ni_mllid;
args[2] = IEEE80211_REASON_MESH_CLOSE_RCVD;
ieee80211_send_action(ni,
- IEEE80211_ACTION_CAT_MESHPEERING,
+ IEEE80211_ACTION_CAT_SELF_PROT,
IEEE80211_ACTION_MESHPEERING_CLOSE,
args);
mesh_linkchange(ni, IEEE80211_NODE_MESH_HOLDING);
@@ -1883,7 +2252,7 @@
break;
case IEEE80211_NODE_MESH_HOLDING:
mesh_linkchange(ni, IEEE80211_NODE_MESH_IDLE);
- mesh_peer_timeout_setup(ni);
+ mesh_peer_timeout_stop(ni);
break;
}
return 0;
@@ -1991,7 +2360,7 @@
frm = ieee80211_add_xrates(frm, rs);
frm = ieee80211_add_meshid(frm, vap);
frm = ieee80211_add_meshconf(frm, vap);
- frm = ieee80211_add_meshpeer(frm, IEEE80211_MESH_PEER_LINK_OPEN,
+ frm = ieee80211_add_meshpeer(frm, IEEE80211_ACTION_MESHPEERING_OPEN,
args[0], 0, 0);
m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *);
return mesh_send_action(ni, m);
@@ -2059,7 +2428,7 @@
frm = ieee80211_add_meshid(frm, vap);
frm = ieee80211_add_meshconf(frm, vap);
frm = ieee80211_add_meshpeer(frm,
- IEEE80211_MESH_PEER_LINK_CONFIRM,
+ IEEE80211_ACTION_MESHPEERING_CONFIRM,
args[0], args[1], 0);
m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *);
return mesh_send_action(ni, m);
@@ -2101,16 +2470,14 @@
* mesh peer close action frame format:
* [1] category
* [1] action
- * [2] reason code
* [tlv] mesh id
* [tlv] mesh peer link mgmt
*/
*frm++ = category;
*frm++ = action;
- ADDSHORT(frm, args[2]); /* reason code */
frm = ieee80211_add_meshid(frm, vap);
frm = ieee80211_add_meshpeer(frm,
- IEEE80211_MESH_PEER_LINK_CLOSE,
+ IEEE80211_ACTION_MESHPEERING_CLOSE,
args[0], args[1], args[2]);
m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *);
return mesh_send_action(ni, m);
@@ -2234,7 +2601,7 @@
args[0] = ni->ni_mlpid;
args[2] = IEEE80211_REASON_MESH_MAX_RETRIES;
ieee80211_send_action(ni,
- IEEE80211_ACTION_CAT_MESHPEERING,
+ IEEE80211_ACTION_CAT_SELF_PROT,
IEEE80211_ACTION_MESHPEERING_CLOSE, args);
ni->ni_mlrcnt = 0;
mesh_linkchange(ni, IEEE80211_NODE_MESH_HOLDING);
@@ -2242,26 +2609,20 @@
} else {
args[0] = ni->ni_mlpid;
ieee80211_send_action(ni,
- IEEE80211_ACTION_CAT_MESHPEERING,
+ IEEE80211_ACTION_CAT_SELF_PROT,
IEEE80211_ACTION_MESHPEERING_OPEN, args);
ni->ni_mlrcnt++;
mesh_peer_timeout_backoff(ni);
}
break;
case IEEE80211_NODE_MESH_CONFIRMRCV:
- if (ni->ni_mlrcnt == ieee80211_mesh_maxretries) {
- args[0] = ni->ni_mlpid;
- args[2] = IEEE80211_REASON_MESH_CONFIRM_TIMEOUT;
- ieee80211_send_action(ni,
- IEEE80211_ACTION_CAT_MESHPEERING,
- IEEE80211_ACTION_MESHPEERING_CLOSE, args);
- ni->ni_mlrcnt = 0;
- mesh_linkchange(ni, IEEE80211_NODE_MESH_HOLDING);
- mesh_peer_timeout_setup(ni);
- } else {
- ni->ni_mlrcnt++;
- mesh_peer_timeout_setup(ni);
- }
+ args[0] = ni->ni_mlpid;
+ args[2] = IEEE80211_REASON_MESH_CONFIRM_TIMEOUT;
+ ieee80211_send_action(ni,
+ IEEE80211_ACTION_CAT_SELF_PROT,
+ IEEE80211_ACTION_MESHPEERING_CLOSE, args);
+ mesh_linkchange(ni, IEEE80211_NODE_MESH_HOLDING);
+ mesh_peer_timeout_setup(ni);
break;
case IEEE80211_NODE_MESH_HOLDING:
mesh_linkchange(ni, IEEE80211_NODE_MESH_IDLE);
@@ -2337,22 +2698,31 @@
const struct ieee80211_meshpeer_ie *meshpeer =
(const struct ieee80211_meshpeer_ie *) ie;
- if (meshpeer == NULL || meshpeer->peer_len < 6 ||
- meshpeer->peer_len > 10)
+ if (meshpeer == NULL ||
+ meshpeer->peer_len < IEEE80211_MPM_BASE_SZ ||
+ meshpeer->peer_len > IEEE80211_MPM_MAX_SZ)
return 1;
+ if (meshpeer->peer_proto != IEEE80211_MPPID_MPM) {
+ IEEE80211_DPRINTF(vap,
+ IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH,
+ "Only MPM protocol is supported (proto: 0x%02X)",
+ meshpeer->peer_proto);
+ return 1;
+ }
switch (subtype) {
- case IEEE80211_MESH_PEER_LINK_OPEN:
- if (meshpeer->peer_len != 6)
+ case IEEE80211_ACTION_MESHPEERING_OPEN:
+ if (meshpeer->peer_len != IEEE80211_MPM_BASE_SZ)
return 1;
break;
- case IEEE80211_MESH_PEER_LINK_CONFIRM:
- if (meshpeer->peer_len != 8)
+ case IEEE80211_ACTION_MESHPEERING_CONFIRM:
+ if (meshpeer->peer_len != IEEE80211_MPM_BASE_SZ + 2)
return 1;
break;
- case IEEE80211_MESH_PEER_LINK_CLOSE:
- if (meshpeer->peer_len < 8)
+ case IEEE80211_ACTION_MESHPEERING_CLOSE:
+ if (meshpeer->peer_len < IEEE80211_MPM_BASE_SZ + 2)
return 1;
- if (meshpeer->peer_len == 8 && meshpeer->peer_linkid != 0)
+ if (meshpeer->peer_len == (IEEE80211_MPM_BASE_SZ + 2) &&
+ meshpeer->peer_linkid != 0)
return 1;
if (meshpeer->peer_rcode == 0)
return 1;
@@ -2398,9 +2768,10 @@
*frm++ = IEEE80211_MESHCONF_SYNC_NEIGHOFF;
*frm++ = IEEE80211_MESHCONF_AUTH_DISABLED;
/* NB: set the number of neighbors before the rest */
- *frm = (ms->ms_neighbors > 15 ? 15 : ms->ms_neighbors) << 1;
- if (ms->ms_flags & IEEE80211_MESHFLAGS_PORTAL)
- *frm |= IEEE80211_MESHCONF_FORM_MP;
+ *frm = (ms->ms_neighbors > IEEE80211_MESH_MAX_NEIGHBORS ?
+ IEEE80211_MESH_MAX_NEIGHBORS : ms->ms_neighbors) << 1;
+ if (ms->ms_flags & IEEE80211_MESHFLAGS_GATE)
+ *frm |= IEEE80211_MESHCONF_FORM_GATE;
frm += 1;
caps = 0;
if (ms->ms_flags & IEEE80211_MESHFLAGS_AP)
@@ -2418,34 +2789,29 @@
ieee80211_add_meshpeer(uint8_t *frm, uint8_t subtype, uint16_t localid,
uint16_t peerid, uint16_t reason)
{
- /* XXX change for AH */
- static const uint8_t meshpeerproto[4] = IEEE80211_MESH_PEER_PROTO;
KASSERT(localid != 0, ("localid == 0"));
*frm++ = IEEE80211_ELEMID_MESHPEER;
switch (subtype) {
- case IEEE80211_MESH_PEER_LINK_OPEN:
- *frm++ = 6; /* length */
- memcpy(frm, meshpeerproto, 4);
- frm += 4;
- ADDSHORT(frm, localid); /* local ID */
+ case IEEE80211_ACTION_MESHPEERING_OPEN:
+ *frm++ = IEEE80211_MPM_BASE_SZ; /* length */
+ ADDSHORT(frm, IEEE80211_MPPID_MPM); /* proto */
+ ADDSHORT(frm, localid); /* local ID */
break;
- case IEEE80211_MESH_PEER_LINK_CONFIRM:
+ case IEEE80211_ACTION_MESHPEERING_CONFIRM:
KASSERT(peerid != 0, ("sending peer confirm without peer id"));
- *frm++ = 8; /* length */
- memcpy(frm, meshpeerproto, 4);
- frm += 4;
- ADDSHORT(frm, localid); /* local ID */
- ADDSHORT(frm, peerid); /* peer ID */
+ *frm++ = IEEE80211_MPM_BASE_SZ + 2; /* length */
+ ADDSHORT(frm, IEEE80211_MPPID_MPM); /* proto */
+ ADDSHORT(frm, localid); /* local ID */
+ ADDSHORT(frm, peerid); /* peer ID */
break;
- case IEEE80211_MESH_PEER_LINK_CLOSE:
+ case IEEE80211_ACTION_MESHPEERING_CLOSE:
if (peerid)
- *frm++ = 10; /* length */
+ *frm++ = IEEE80211_MPM_MAX_SZ; /* length */
else
- *frm++ = 8; /* length */
- memcpy(frm, meshpeerproto, 4);
- frm += 4;
+ *frm++ = IEEE80211_MPM_BASE_SZ + 2; /* length */
+ ADDSHORT(frm, IEEE80211_MPPID_MPM); /* proto */
ADDSHORT(frm, localid); /* local ID */
if (peerid)
ADDSHORT(frm, peerid); /* peer ID */
@@ -2465,7 +2831,7 @@
*/
#define IEEE80211_MESH_MAXOVERHEAD \
(sizeof(struct ieee80211_qosframe_addr4) \
- + sizeof(struct ieee80211_meshcntl_ae11) \
+ + sizeof(struct ieee80211_meshcntl_ae10) \
+ sizeof(struct llc) \
+ IEEE80211_ADDR_LEN \
+ IEEE80211_WEP_IVLEN \
@@ -2597,6 +2963,9 @@
case IEEE80211_IOC_MESH_FWRD:
ireq->i_val = (ms->ms_flags & IEEE80211_MESHFLAGS_FWD) != 0;
break;
+ case IEEE80211_IOC_MESH_GATE:
+ ireq->i_val = (ms->ms_flags & IEEE80211_MESHFLAGS_GATE) != 0;
+ break;
case IEEE80211_IOC_MESH_TTL:
ireq->i_val = ms->ms_ttl;
break;
@@ -2625,15 +2994,16 @@
break;
imr = (struct ieee80211req_mesh_route *)
(p + off);
- imr->imr_flags = rt->rt_flags;
IEEE80211_ADDR_COPY(imr->imr_dest,
rt->rt_dest);
IEEE80211_ADDR_COPY(imr->imr_nexthop,
rt->rt_nexthop);
imr->imr_metric = rt->rt_metric;
imr->imr_nhops = rt->rt_nhops;
- imr->imr_lifetime = rt->rt_lifetime;
+ imr->imr_lifetime =
+ ieee80211_mesh_rt_update(rt, 0);
imr->imr_lastmseq = rt->rt_lastmseq;
+ imr->imr_flags = rt->rt_flags; /* last */
off += sizeof(*imr);
}
MESH_RT_UNLOCK(ms);
@@ -2711,6 +3081,12 @@
else
ms->ms_flags &= ~IEEE80211_MESHFLAGS_FWD;
break;
+ case IEEE80211_IOC_MESH_GATE:
+ if (ireq->i_val)
+ ms->ms_flags |= IEEE80211_MESHFLAGS_GATE;
+ else
+ ms->ms_flags &= ~IEEE80211_MESHFLAGS_GATE;
+ break;
case IEEE80211_IOC_MESH_TTL:
ms->ms_ttl = (uint8_t) ireq->i_val;
break;
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/net80211/ieee80211_mesh.h
--- a/head/sys/net80211/ieee80211_mesh.h Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/net80211/ieee80211_mesh.h Wed Jul 25 16:47:10 2012 +0300
@@ -26,12 +26,13 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: head/sys/net80211/ieee80211_mesh.h 232625 2012-03-06 21:20:16Z adrian $
+ * $FreeBSD: head/sys/net80211/ieee80211_mesh.h 234894 2012-05-01 16:16:20Z monthadar $
*/
#ifndef _NET80211_IEEE80211_MESH_H_
#define _NET80211_IEEE80211_MESH_H_
#define IEEE80211_MESH_DEFAULT_TTL 31
+#define IEEE80211_MESH_MAX_NEIGHBORS 15
/*
* NB: all structures are __packed so sizeof works on arm, et. al.
@@ -97,7 +98,7 @@
};
/* Mesh Formation Info */
-#define IEEE80211_MESHCONF_FORM_MP 0x01 /* Connected to Portal */
+#define IEEE80211_MESHCONF_FORM_GATE 0x01 /* Connected to Gate */
#define IEEE80211_MESHCONF_FORM_NNEIGH_MASK 0x7E /* Number of Neighbours */
#define IEEE80211_MESHCONF_FORM_SA 0xF0 /* indicating 802.1X auth */
@@ -140,32 +141,24 @@
} __packed;
/* Peer Link Management */
+#define IEEE80211_MPM_BASE_SZ (4)
+#define IEEE80211_MPM_MAX_SZ (8)
struct ieee80211_meshpeer_ie {
uint8_t peer_ie; /* IEEE80211_ELEMID_MESHPEER */
uint8_t peer_len;
- uint8_t peer_proto[4]; /* Peer Management Protocol */
+ uint16_t peer_proto; /* Peer Management Protocol */
uint16_t peer_llinkid; /* Local Link ID */
uint16_t peer_linkid; /* Peer Link ID */
uint16_t peer_rcode;
} __packed;
+/* Mesh Peering Protocol Identifier field value */
enum {
- IEEE80211_MESH_PEER_LINK_OPEN = 0,
- IEEE80211_MESH_PEER_LINK_CONFIRM = 1,
- IEEE80211_MESH_PEER_LINK_CLOSE = 2,
- /* values 3-255 are reserved */
+ IEEE80211_MPPID_MPM = 0, /* Mesh peering management */
+ IEEE80211_MPPID_AUTH_MPM = 1, /* Auth. mesh peering exchange */
+ /* 2-65535 reserved */
};
-/* Mesh Peering Management Protocol */
-#define IEEE80211_MESH_PEER_PROTO_OUI 0x00, 0x0f, 0xac
-#define IEEE80211_MESH_PEER_PROTO_VALUE 0x2a
-#define IEEE80211_MESH_PEER_PROTO { IEEE80211_MESH_PEER_PROTO_OUI, \
- IEEE80211_MESH_PEER_PROTO_VALUE }
-/* Abbreviated Handshake Protocol */
-#define IEEE80211_MESH_PEER_PROTO_AH_OUI 0x00, 0x0f, 0xac
-#define IEEE80211_MESH_PEER_PROTO_AH_VALUE 0x2b
-#define IEEE80211_MESH_PEER_PROTO_AH { IEEE80211_MESH_PEER_PROTO_AH_OUI, \
- IEEE80211_MESH_PEER_PROTO_AH_VALUE }
#ifdef notyet
/* Mesh Channel Switch Annoucement */
struct ieee80211_meshcsa_ie {
@@ -200,9 +193,9 @@
} __packed;
#endif
-/* Portal (MP) Annoucement */
-struct ieee80211_meshpann_ie {
- uint8_t pann_ie; /* IEEE80211_ELEMID_MESHPANN */
+/* Gate (GANN) Annoucement */
+struct ieee80211_meshgann_ie {
+ uint8_t pann_ie; /* IEEE80211_ELEMID_MESHGANN */
uint8_t pann_len;
uint8_t pann_flags;
uint8_t pann_hopcount;
@@ -217,7 +210,7 @@
uint8_t rann_ie; /* IEEE80211_ELEMID_MESHRANN */
uint8_t rann_len;
uint8_t rann_flags;
-#define IEEE80211_MESHRANN_FLAGS_PR 0x01 /* Portal Role */
+#define IEEE80211_MESHRANN_FLAGS_GATE 0x01 /* Mesh Gate */
uint8_t rann_hopcount;
uint8_t rann_ttl;
uint8_t rann_addr[IEEE80211_ADDR_LEN];
@@ -236,8 +229,8 @@
uint8_t preq_ie; /* IEEE80211_ELEMID_MESHPREQ */
uint8_t preq_len;
uint8_t preq_flags;
-#define IEEE80211_MESHPREQ_FLAGS_PR 0x01 /* Portal Role */
-#define IEEE80211_MESHPREQ_FLAGS_AM 0x02 /* 0 = ucast / 1 = bcast */
+#define IEEE80211_MESHPREQ_FLAGS_GATE 0x01 /* Mesh Gate */
+#define IEEE80211_MESHPREQ_FLAGS_AM 0x02 /* 0 = bcast / 1 = ucast */
#define IEEE80211_MESHPREQ_FLAGS_PP 0x04 /* Proactive PREP */
#define IEEE80211_MESHPREQ_FLAGS_AE 0x40 /* Address Extension */
uint8_t preq_hopcount;
@@ -253,7 +246,6 @@
struct {
uint8_t target_flags;
#define IEEE80211_MESHPREQ_TFLAGS_TO 0x01 /* Target Only */
-#define IEEE80211_MESHPREQ_TFLAGS_RF 0x02 /* Reply and Forward */
#define IEEE80211_MESHPREQ_TFLAGS_USN 0x04 /* Unknown HWMP seq number */
uint8_t target_addr[IEEE80211_ADDR_LEN];
uint32_t target_seq; /* HWMP Sequence Number */
@@ -331,9 +323,9 @@
/*
* 802.11s Action Frames
+ * XXX: these are wrong, and some of them should be
+ * under MESH category while PROXY is under MULTIHOP category.
*/
-#define IEEE80211_ACTION_CAT_MESHPEERING 30 /* XXX Linux */
-/* XXX: these need to be looked into */
#define IEEE80211_ACTION_CAT_INTERWORK 15
#define IEEE80211_ACTION_CAT_RESOURCE 16
#define IEEE80211_ACTION_CAT_PROXY 17
@@ -342,10 +334,11 @@
* Mesh Peering Action codes.
*/
enum {
- IEEE80211_ACTION_MESHPEERING_OPEN = 0,
- IEEE80211_ACTION_MESHPEERING_CONFIRM = 1,
- IEEE80211_ACTION_MESHPEERING_CLOSE = 2,
- /* 3-255 reserved */
+ /* 0 reserved */
+ IEEE80211_ACTION_MESHPEERING_OPEN = 1,
+ IEEE80211_ACTION_MESHPEERING_CONFIRM = 2,
+ IEEE80211_ACTION_MESHPEERING_CLOSE = 3,
+ /* 4-255 reserved */
};
/*
@@ -367,14 +360,6 @@
};
/*
- * Mesh Portal Annoucement Action codes.
- */
-enum {
- IEEE80211_ACTION_MESHPANN = 0,
- /* 1-255 reserved */
-};
-
-/*
* Different mesh control structures based on the AE
* (Address Extension) bits.
*/
@@ -396,37 +381,51 @@
uint8_t mc_flags; /* Address Extension 10 */
uint8_t mc_ttl; /* TTL */
uint8_t mc_seq[4]; /* Sequence No. */
- uint8_t mc_addr4[IEEE80211_ADDR_LEN];
- uint8_t mc_addr5[IEEE80211_ADDR_LEN];
-} __packed;
-
-struct ieee80211_meshcntl_ae11 {
- uint8_t mc_flags; /* Address Extension 11 */
- uint8_t mc_ttl; /* TTL */
- uint8_t mc_seq[4]; /* Sequence No. */
- uint8_t mc_addr4[IEEE80211_ADDR_LEN];
uint8_t mc_addr5[IEEE80211_ADDR_LEN];
uint8_t mc_addr6[IEEE80211_ADDR_LEN];
} __packed;
+#define IEEE80211_MESH_AE_MASK 0x03
+enum {
+ IEEE80211_MESH_AE_00 = 0, /* MC has no AE subfield */
+ IEEE80211_MESH_AE_01 = 1, /* MC contain addr4 */
+ IEEE80211_MESH_AE_10 = 2, /* MC contain addr5 & addr6 */
+ IEEE80211_MESH_AE_11 = 3, /* RESERVED */
+};
+
#ifdef _KERNEL
MALLOC_DECLARE(M_80211_MESH_PREQ);
MALLOC_DECLARE(M_80211_MESH_PREP);
MALLOC_DECLARE(M_80211_MESH_PERR);
MALLOC_DECLARE(M_80211_MESH_RT);
+/*
+ * Basic forwarding information:
+ * o Destination MAC
+ * o Next-hop MAC
+ * o Precursor list (not implemented yet)
+ * o Path timeout
+ * The rest is part of the active Mesh path selection protocol.
+ * XXX: to be moved out later.
+ */
struct ieee80211_mesh_route {
TAILQ_ENTRY(ieee80211_mesh_route) rt_next;
- int rt_crtime; /* creation time */
+ struct ieee80211vap *rt_vap;
+ struct mtx rt_lock; /* fine grained route lock */
+ struct callout rt_discovery; /* discovery timeout */
+ int rt_updtime; /* last update time */
uint8_t rt_dest[IEEE80211_ADDR_LEN];
+ uint8_t rt_mesh_gate[IEEE80211_ADDR_LEN]; /* meshDA */
uint8_t rt_nexthop[IEEE80211_ADDR_LEN];
uint32_t rt_metric; /* path metric */
uint16_t rt_nhops; /* number of hops */
uint16_t rt_flags;
-#define IEEE80211_MESHRT_FLAGS_VALID 0x01 /* patch discovery complete */
-#define IEEE80211_MESHRT_FLAGS_PROXY 0x02 /* proxy entry */
- uint32_t rt_lifetime;
+#define IEEE80211_MESHRT_FLAGS_DISCOVER 0x01 /* path discovery */
+#define IEEE80211_MESHRT_FLAGS_VALID 0x02 /* path discovery complete */
+#define IEEE80211_MESHRT_FLAGS_PROXY 0x04 /* proxy entry */
+ uint32_t rt_lifetime; /* route timeout */
uint32_t rt_lastmseq; /* last seq# seen dest */
+ uint32_t rt_ext_seq; /* proxy seq number */
void *rt_priv; /* private data */
};
#define IEEE80211_MESH_ROUTE_PRIV(rt, cast) ((cast *)rt->rt_priv)
@@ -445,6 +444,9 @@
const uint8_t [IEEE80211_ADDR_LEN],
struct mbuf *);
void (*mpp_peerdown)(struct ieee80211_node *);
+ void (*mpp_senderror)(struct ieee80211vap *,
+ const uint8_t [IEEE80211_ADDR_LEN],
+ struct ieee80211_mesh_route *, int);
void (*mpp_vattach)(struct ieee80211vap *);
void (*mpp_vdetach)(struct ieee80211vap *);
int (*mpp_newstate)(struct ieee80211vap *,
@@ -491,7 +493,7 @@
uint16_t ms_neighbors;
uint8_t ms_ttl; /* mesh ttl set in packets */
#define IEEE80211_MESHFLAGS_AP 0x01 /* accept peers */
-#define IEEE80211_MESHFLAGS_PORTAL 0x02 /* mesh portal role */
+#define IEEE80211_MESHFLAGS_GATE 0x02 /* mesh gate role */
#define IEEE80211_MESHFLAGS_FWD 0x04 /* forward packets */
uint8_t ms_flags;
struct mtx ms_rt_lock;
@@ -514,6 +516,7 @@
void ieee80211_mesh_rt_flush(struct ieee80211vap *);
void ieee80211_mesh_rt_flush_peer(struct ieee80211vap *,
const uint8_t [IEEE80211_ADDR_LEN]);
+int ieee80211_mesh_rt_update(struct ieee80211_mesh_route *rt, int);
void ieee80211_mesh_proxy_check(struct ieee80211vap *,
const uint8_t [IEEE80211_ADDR_LEN]);
@@ -548,7 +551,7 @@
{
struct ieee80211_mesh_state *ms = vap->iv_mesh;
return (ms->ms_flags &
- (IEEE80211_MESHFLAGS_AP | IEEE80211_MESHFLAGS_PORTAL)) != 0;
+ (IEEE80211_MESHFLAGS_AP | IEEE80211_MESHFLAGS_GATE)) != 0;
}
/*
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/net80211/ieee80211_output.c
--- a/head/sys/net80211/ieee80211_output.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/net80211/ieee80211_output.c Wed Jul 25 16:47:10 2012 +0300
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_output.c 234324 2012-04-15 20:29:39Z adrian $");
+__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_output.c 237561 2012-06-25 11:52:26Z monthadar $");
#include "opt_inet.h"
#include "opt_inet6.h"
@@ -254,7 +254,7 @@
if (!ieee80211_mesh_isproxyena(vap)) {
IEEE80211_DISCARD_MAC(vap,
IEEE80211_MSG_OUTPUT |
- IEEE80211_MSG_MESH,
+ IEEE80211_MSG_MESH,
eh->ether_dhost, NULL,
"%s", "proxy not enabled");
vap->iv_stats.is_mesh_notproxy++;
@@ -363,7 +363,6 @@
continue;
}
}
-
error = parent->if_transmit(parent, m);
if (error != 0) {
/* NB: IFQ_HANDOFF reclaims mbuf */
@@ -556,7 +555,6 @@
break;
case IEEE80211_M_MBSS:
#ifdef IEEE80211_SUPPORT_MESH
- /* XXX add support for proxied addresses */
if (IEEE80211_IS_MULTICAST(da)) {
wh->i_fc[1] = IEEE80211_FC1_DIR_FROMDS;
/* XXX next hop */
@@ -1016,10 +1014,13 @@
struct mbuf *m)
{
#define WH4(wh) ((struct ieee80211_frame_addr4 *)(wh))
+#define MC01(mc) ((struct ieee80211_meshcntl_ae01 *)mc)
struct ieee80211com *ic = ni->ni_ic;
#ifdef IEEE80211_SUPPORT_MESH
struct ieee80211_mesh_state *ms = vap->iv_mesh;
struct ieee80211_meshcntl_ae10 *mc;
+ struct ieee80211_mesh_route *rt = NULL;
+ int dir = -1;
#endif
struct ether_header eh;
struct ieee80211_frame *wh;
@@ -1100,21 +1101,40 @@
* w/ 4-address format and address extension mode 10
*/
is4addr = 0; /* NB: don't use, disable */
- if (!IEEE80211_IS_MULTICAST(eh.ether_dhost))
- hdrsize += IEEE80211_ADDR_LEN; /* unicast are 4-addr */
- meshhdrsize = sizeof(struct ieee80211_meshcntl);
- /* XXX defines for AE modes */
- if (IEEE80211_ADDR_EQ(eh.ether_shost, vap->iv_myaddr)) {
- if (!IEEE80211_IS_MULTICAST(eh.ether_dhost))
- meshae = 0;
- else
- meshae = 4; /* NB: pseudo */
- } else if (IEEE80211_IS_MULTICAST(eh.ether_dhost)) {
- meshae = 1;
- meshhdrsize += 1*IEEE80211_ADDR_LEN;
+ if (!IEEE80211_IS_MULTICAST(eh.ether_dhost)) {
+ rt = ieee80211_mesh_rt_find(vap, eh.ether_dhost);
+ KASSERT(rt != NULL, ("route is NULL"));
+ dir = IEEE80211_FC1_DIR_DSTODS;
+ hdrsize += IEEE80211_ADDR_LEN;
+ if (rt->rt_flags & IEEE80211_MESHRT_FLAGS_PROXY) {
+ if (IEEE80211_ADDR_EQ(rt->rt_mesh_gate,
+ vap->iv_myaddr)) {
+ IEEE80211_NOTE_MAC(vap,
+ IEEE80211_MSG_MESH,
+ eh.ether_dhost,
+ "%s", "trying to send to ourself");
+ goto bad;
+ }
+ meshae = IEEE80211_MESH_AE_10;
+ meshhdrsize =
+ sizeof(struct ieee80211_meshcntl_ae10);
+ } else {
+ meshae = IEEE80211_MESH_AE_00;
+ meshhdrsize =
+ sizeof(struct ieee80211_meshcntl);
+ }
} else {
- meshae = 2;
- meshhdrsize += 2*IEEE80211_ADDR_LEN;
+ dir = IEEE80211_FC1_DIR_FROMDS;
+ if (!IEEE80211_ADDR_EQ(eh.ether_shost, vap->iv_myaddr)) {
+ /* proxy group */
+ meshae = IEEE80211_MESH_AE_01;
+ meshhdrsize =
+ sizeof(struct ieee80211_meshcntl_ae01);
+ } else {
+ /* group */
+ meshae = IEEE80211_MESH_AE_00;
+ meshhdrsize = sizeof(struct ieee80211_meshcntl);
+ }
}
} else {
#endif
@@ -1215,44 +1235,52 @@
/* NB: offset by hdrspace to deal with DATAPAD */
mc = (struct ieee80211_meshcntl_ae10 *)
(mtod(m, uint8_t *) + hdrspace);
+ wh->i_fc[1] = dir;
switch (meshae) {
- case 0: /* ucast, no proxy */
- wh->i_fc[1] = IEEE80211_FC1_DIR_DSTODS;
- IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_macaddr);
- IEEE80211_ADDR_COPY(wh->i_addr2, vap->iv_myaddr);
- IEEE80211_ADDR_COPY(wh->i_addr3, eh.ether_dhost);
- IEEE80211_ADDR_COPY(WH4(wh)->i_addr4, eh.ether_shost);
+ case IEEE80211_MESH_AE_00: /* no proxy */
mc->mc_flags = 0;
- qos = ((struct ieee80211_qosframe_addr4 *) wh)->i_qos;
+ if (dir == IEEE80211_FC1_DIR_DSTODS) { /* ucast */
+ IEEE80211_ADDR_COPY(wh->i_addr1,
+ ni->ni_macaddr);
+ IEEE80211_ADDR_COPY(wh->i_addr2,
+ vap->iv_myaddr);
+ IEEE80211_ADDR_COPY(wh->i_addr3,
+ eh.ether_dhost);
+ IEEE80211_ADDR_COPY(WH4(wh)->i_addr4,
+ eh.ether_shost);
+ qos =((struct ieee80211_qosframe_addr4 *)
+ wh)->i_qos;
+ } else if (dir == IEEE80211_FC1_DIR_FROMDS) {
+ /* mcast */
+ IEEE80211_ADDR_COPY(wh->i_addr1,
+ eh.ether_dhost);
+ IEEE80211_ADDR_COPY(wh->i_addr2,
+ vap->iv_myaddr);
+ IEEE80211_ADDR_COPY(wh->i_addr3,
+ eh.ether_shost);
+ qos = ((struct ieee80211_qosframe *)
+ wh)->i_qos;
+ }
break;
- case 4: /* mcast, no proxy */
- wh->i_fc[1] = IEEE80211_FC1_DIR_FROMDS;
- IEEE80211_ADDR_COPY(wh->i_addr1, eh.ether_dhost);
- IEEE80211_ADDR_COPY(wh->i_addr2, vap->iv_myaddr);
- IEEE80211_ADDR_COPY(wh->i_addr3, eh.ether_shost);
- mc->mc_flags = 0; /* NB: AE is really 0 */
- qos = ((struct ieee80211_qosframe *) wh)->i_qos;
- break;
- case 1: /* mcast, proxy */
+ case IEEE80211_MESH_AE_01: /* mcast, proxy */
wh->i_fc[1] = IEEE80211_FC1_DIR_FROMDS;
IEEE80211_ADDR_COPY(wh->i_addr1, eh.ether_dhost);
IEEE80211_ADDR_COPY(wh->i_addr2, vap->iv_myaddr);
IEEE80211_ADDR_COPY(wh->i_addr3, vap->iv_myaddr);
mc->mc_flags = 1;
- IEEE80211_ADDR_COPY(mc->mc_addr4, eh.ether_shost);
+ IEEE80211_ADDR_COPY(MC01(mc)->mc_addr4,
+ eh.ether_shost);
qos = ((struct ieee80211_qosframe *) wh)->i_qos;
break;
- case 2: /* ucast, proxy */
- wh->i_fc[1] = IEEE80211_FC1_DIR_DSTODS;
- IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_macaddr);
+ case IEEE80211_MESH_AE_10: /* ucast, proxy */
+ KASSERT(rt != NULL, ("route is NULL"));
+ IEEE80211_ADDR_COPY(wh->i_addr1, rt->rt_nexthop);
IEEE80211_ADDR_COPY(wh->i_addr2, vap->iv_myaddr);
- /* XXX not right, need MeshDA */
- IEEE80211_ADDR_COPY(wh->i_addr3, eh.ether_dhost);
- /* XXX assume are MeshSA */
+ IEEE80211_ADDR_COPY(wh->i_addr3, rt->rt_mesh_gate);
IEEE80211_ADDR_COPY(WH4(wh)->i_addr4, vap->iv_myaddr);
- mc->mc_flags = 2;
- IEEE80211_ADDR_COPY(mc->mc_addr4, eh.ether_dhost);
- IEEE80211_ADDR_COPY(mc->mc_addr5, eh.ether_shost);
+ mc->mc_flags = IEEE80211_MESH_AE_10;
+ IEEE80211_ADDR_COPY(mc->mc_addr5, eh.ether_dhost);
+ IEEE80211_ADDR_COPY(mc->mc_addr6, eh.ether_shost);
qos = ((struct ieee80211_qosframe_addr4 *) wh)->i_qos;
break;
default:
@@ -1285,9 +1313,9 @@
if (ic->ic_wme.wme_wmeChanParams.cap_wmeParams[ac].wmep_noackPolicy)
qos[0] |= IEEE80211_QOS_ACKPOLICY_NOACK;
#ifdef IEEE80211_SUPPORT_MESH
- if (vap->iv_opmode == IEEE80211_M_MBSS) {
- qos[1] |= IEEE80211_QOS_MC;
- } else
+ if (vap->iv_opmode == IEEE80211_M_MBSS)
+ qos[1] = IEEE80211_QOS_MC;
+ else
#endif
qos[1] = 0;
wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_QOS;
@@ -1363,6 +1391,7 @@
m_freem(m);
return NULL;
#undef WH4
+#undef MC01
}
/*
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/net80211/ieee80211_radiotap.c
--- a/head/sys/net80211/ieee80211_radiotap.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/net80211/ieee80211_radiotap.c Wed Jul 25 16:47:10 2012 +0300
@@ -24,7 +24,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_radiotap.c 232705 2012-03-08 23:46:42Z adrian $");
+__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_radiotap.c 237214 2012-06-18 02:08:04Z adrian $");
/*
* IEEE 802.11 radiotap support.
@@ -47,13 +47,24 @@
#include <net80211/ieee80211_var.h>
-static int radiotap_offset(struct ieee80211_radiotap_header *, int);
+static int radiotap_offset(struct ieee80211_radiotap_header *, int, int);
void
ieee80211_radiotap_attach(struct ieee80211com *ic,
struct ieee80211_radiotap_header *th, int tlen, uint32_t tx_radiotap,
struct ieee80211_radiotap_header *rh, int rlen, uint32_t rx_radiotap)
{
+ ieee80211_radiotap_attachv(ic, th, tlen, 0, tx_radiotap,
+ rh, rlen, 0, rx_radiotap);
+}
+
+void
+ieee80211_radiotap_attachv(struct ieee80211com *ic,
+ struct ieee80211_radiotap_header *th,
+ int tlen, int n_tx_v, uint32_t tx_radiotap,
+ struct ieee80211_radiotap_header *rh,
+ int rlen, int n_rx_v, uint32_t rx_radiotap)
+{
#define B(_v) (1<<(_v))
int off;
@@ -63,9 +74,9 @@
/* calculate offset to channel data */
off = -1;
if (tx_radiotap & B(IEEE80211_RADIOTAP_CHANNEL))
- off = radiotap_offset(th, IEEE80211_RADIOTAP_CHANNEL);
+ off = radiotap_offset(th, n_tx_v, IEEE80211_RADIOTAP_CHANNEL);
else if (tx_radiotap & B(IEEE80211_RADIOTAP_XCHANNEL))
- off = radiotap_offset(th, IEEE80211_RADIOTAP_XCHANNEL);
+ off = radiotap_offset(th, n_tx_v, IEEE80211_RADIOTAP_XCHANNEL);
if (off == -1) {
if_printf(ic->ic_ifp, "%s: no tx channel, radiotap 0x%x\n",
__func__, tx_radiotap);
@@ -79,9 +90,9 @@
/* calculate offset to channel data */
off = -1;
if (rx_radiotap & B(IEEE80211_RADIOTAP_CHANNEL))
- off = radiotap_offset(rh, IEEE80211_RADIOTAP_CHANNEL);
+ off = radiotap_offset(rh, n_rx_v, IEEE80211_RADIOTAP_CHANNEL);
else if (rx_radiotap & B(IEEE80211_RADIOTAP_XCHANNEL))
- off = radiotap_offset(rh, IEEE80211_RADIOTAP_XCHANNEL);
+ off = radiotap_offset(rh, n_rx_v, IEEE80211_RADIOTAP_XCHANNEL);
if (off == -1) {
if_printf(ic->ic_ifp, "%s: no rx channel, radiotap 0x%x\n",
__func__, rx_radiotap);
@@ -260,7 +271,8 @@
* known -1 is returned.
*/
static int
-radiotap_offset(struct ieee80211_radiotap_header *rh, int item)
+radiotap_offset(struct ieee80211_radiotap_header *rh,
+ int n_vendor_attributes, int item)
{
static const struct {
size_t align, width;
@@ -334,6 +346,8 @@
int off, i;
off = sizeof(struct ieee80211_radiotap_header);
+ off += n_vendor_attributes * (sizeof(uint32_t));
+
for (i = 0; i < IEEE80211_RADIOTAP_EXT; i++) {
if ((present & (1<<i)) == 0)
continue;
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/net80211/ieee80211_var.h
--- a/head/sys/net80211/ieee80211_var.h Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/net80211/ieee80211_var.h Wed Jul 25 16:47:10 2012 +0300
@@ -23,7 +23,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $FreeBSD: head/sys/net80211/ieee80211_var.h 233452 2012-03-25 03:11:57Z adrian $
+ * $FreeBSD: head/sys/net80211/ieee80211_var.h 237214 2012-06-18 02:08:04Z adrian $
*/
#ifndef _NET80211_IEEE80211_VAR_H_
#define _NET80211_IEEE80211_VAR_H_
@@ -705,6 +705,11 @@
uint32_t tx_radiotap,
struct ieee80211_radiotap_header *rh, int rlen,
uint32_t rx_radiotap);
+void ieee80211_radiotap_attachv(struct ieee80211com *,
+ struct ieee80211_radiotap_header *th,
+ int tlen, int n_tx_v, uint32_t tx_radiotap,
+ struct ieee80211_radiotap_header *rh,
+ int rlen, int n_rx_v, uint32_t rx_radiotap);
void ieee80211_radiotap_detach(struct ieee80211com *);
void ieee80211_radiotap_vattach(struct ieee80211vap *);
void ieee80211_radiotap_vdetach(struct ieee80211vap *);
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/netgraph/netflow/netflow.c
--- a/head/sys/netgraph/netflow/netflow.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/netgraph/netflow/netflow.c Wed Jul 25 16:47:10 2012 +0300
@@ -29,7 +29,7 @@
*/
static const char rcs_id[] =
- "@(#) $FreeBSD: head/sys/netgraph/netflow/netflow.c 232921 2012-03-13 11:08:40Z melifaro $";
+ "@(#) $FreeBSD: head/sys/netgraph/netflow/netflow.c 237227 2012-06-18 13:56:36Z melifaro $";
#include "opt_inet6.h"
#include "opt_route.h"
@@ -98,9 +98,9 @@
static int export_add(item_p, struct flow_entry *);
static int export_send(priv_p, fib_export_p, item_p, int);
-static int hash_insert(priv_p, struct flow_hash_entry *, struct flow_rec *, int, uint8_t);
+static int hash_insert(priv_p, struct flow_hash_entry *, struct flow_rec *, int, uint8_t, uint8_t);
#ifdef INET6
-static int hash6_insert(priv_p, struct flow_hash_entry *, struct flow6_rec *, int, uint8_t);
+static int hash6_insert(priv_p, struct flow_hash_entry *, struct flow6_rec *, int, uint8_t, uint8_t);
#endif
static __inline void expire_flow(priv_p, fib_export_p, struct flow_entry *, int);
@@ -325,9 +325,9 @@
* as this was done in previous version. Need to test & profile
* to be sure.
*/
-static __inline int
+static int
hash_insert(priv_p priv, struct flow_hash_entry *hsh, struct flow_rec *r,
- int plen, uint8_t tcp_flags)
+ int plen, uint8_t flags, uint8_t tcp_flags)
{
struct flow_entry *fle;
struct sockaddr_in sin;
@@ -358,44 +358,48 @@
* First we do route table lookup on destination address. So we can
* fill in out_ifx, dst_mask, nexthop, and dst_as in future releases.
*/
- bzero(&sin, sizeof(sin));
- sin.sin_len = sizeof(struct sockaddr_in);
- sin.sin_family = AF_INET;
- sin.sin_addr = fle->f.r.r_dst;
- rt = rtalloc1_fib((struct sockaddr *)&sin, 0, 0, r->fib);
- if (rt != NULL) {
- fle->f.fle_o_ifx = rt->rt_ifp->if_index;
+ if ((flags & NG_NETFLOW_CONF_NODSTLOOKUP) == 0) {
+ bzero(&sin, sizeof(sin));
+ sin.sin_len = sizeof(struct sockaddr_in);
+ sin.sin_family = AF_INET;
+ sin.sin_addr = fle->f.r.r_dst;
+ rt = rtalloc1_fib((struct sockaddr *)&sin, 0, 0, r->fib);
+ if (rt != NULL) {
+ fle->f.fle_o_ifx = rt->rt_ifp->if_index;
- if (rt->rt_flags & RTF_GATEWAY &&
- rt->rt_gateway->sa_family == AF_INET)
- fle->f.next_hop =
- ((struct sockaddr_in *)(rt->rt_gateway))->sin_addr;
+ if (rt->rt_flags & RTF_GATEWAY &&
+ rt->rt_gateway->sa_family == AF_INET)
+ fle->f.next_hop =
+ ((struct sockaddr_in *)(rt->rt_gateway))->sin_addr;
- if (rt_mask(rt))
- fle->f.dst_mask = bitcount32(((struct sockaddr_in *)
- rt_mask(rt))->sin_addr.s_addr);
- else if (rt->rt_flags & RTF_HOST)
- /* Give up. We can't determine mask :( */
- fle->f.dst_mask = 32;
+ if (rt_mask(rt))
+ fle->f.dst_mask = bitcount32(((struct sockaddr_in *)
+ rt_mask(rt))->sin_addr.s_addr);
+ else if (rt->rt_flags & RTF_HOST)
+ /* Give up. We can't determine mask :( */
+ fle->f.dst_mask = 32;
- RTFREE_LOCKED(rt);
+ RTFREE_LOCKED(rt);
+ }
}
/* Do route lookup on source address, to fill in src_mask. */
- bzero(&sin, sizeof(sin));
- sin.sin_len = sizeof(struct sockaddr_in);
- sin.sin_family = AF_INET;
- sin.sin_addr = fle->f.r.r_src;
- rt = rtalloc1_fib((struct sockaddr *)&sin, 0, 0, r->fib);
- if (rt != NULL) {
- if (rt_mask(rt))
- fle->f.src_mask = bitcount32(((struct sockaddr_in *)
- rt_mask(rt))->sin_addr.s_addr);
- else if (rt->rt_flags & RTF_HOST)
- /* Give up. We can't determine mask :( */
- fle->f.src_mask = 32;
+ if ((flags & NG_NETFLOW_CONF_NOSRCLOOKUP) == 0) {
+ bzero(&sin, sizeof(sin));
+ sin.sin_len = sizeof(struct sockaddr_in);
+ sin.sin_family = AF_INET;
+ sin.sin_addr = fle->f.r.r_src;
+ rt = rtalloc1_fib((struct sockaddr *)&sin, 0, 0, r->fib);
+ if (rt != NULL) {
+ if (rt_mask(rt))
+ fle->f.src_mask = bitcount32(((struct sockaddr_in *)
+ rt_mask(rt))->sin_addr.s_addr);
+ else if (rt->rt_flags & RTF_HOST)
+ /* Give up. We can't determine mask :( */
+ fle->f.src_mask = 32;
- RTFREE_LOCKED(rt);
+ RTFREE_LOCKED(rt);
+ }
}
/* Push new flow at the and of hash. */
@@ -410,10 +414,10 @@
bitcount32((x).__u6_addr.__u6_addr32[1]) + \
bitcount32((x).__u6_addr.__u6_addr32[2]) + \
bitcount32((x).__u6_addr.__u6_addr32[3])
-/* XXX: Do we need inline here ? */
-static __inline int
+#define RT_MASK6(x) (ipv6_masklen(((struct sockaddr_in6 *)rt_mask(x))->sin6_addr))
+static int
hash6_insert(priv_p priv, struct flow_hash_entry *hsh6, struct flow6_rec *r,
- int plen, uint8_t tcp_flags)
+ int plen, uint8_t flags, uint8_t tcp_flags)
{
struct flow6_entry *fle6;
struct sockaddr_in6 *src, *dst;
@@ -445,49 +449,55 @@
* First we do route table lookup on destination address. So we can
* fill in out_ifx, dst_mask, nexthop, and dst_as in future releases.
*/
- bzero(&rin6, sizeof(struct route_in6));
- dst = (struct sockaddr_in6 *)&rin6.ro_dst;
- dst->sin6_len = sizeof(struct sockaddr_in6);
- dst->sin6_family = AF_INET6;
- dst->sin6_addr = r->dst.r_dst6;
+ if ((flags & NG_NETFLOW_CONF_NODSTLOOKUP) == 0)
+ {
+ bzero(&rin6, sizeof(struct route_in6));
+ dst = (struct sockaddr_in6 *)&rin6.ro_dst;
+ dst->sin6_len = sizeof(struct sockaddr_in6);
+ dst->sin6_family = AF_INET6;
+ dst->sin6_addr = r->dst.r_dst6;
- rin6.ro_rt = rtalloc1_fib((struct sockaddr *)dst, 0, 0, r->fib);
+ rin6.ro_rt = rtalloc1_fib((struct sockaddr *)dst, 0, 0, r->fib);
- if (rin6.ro_rt != NULL) {
- rt = rin6.ro_rt;
- fle6->f.fle_o_ifx = rt->rt_ifp->if_index;
+ if (rin6.ro_rt != NULL) {
+ rt = rin6.ro_rt;
+ fle6->f.fle_o_ifx = rt->rt_ifp->if_index;
- if (rt->rt_flags & RTF_GATEWAY &&
- rt->rt_gateway->sa_family == AF_INET6)
- fle6->f.n.next_hop6 =
- ((struct sockaddr_in6 *)(rt->rt_gateway))->sin6_addr;
+ if (rt->rt_flags & RTF_GATEWAY &&
+ rt->rt_gateway->sa_family == AF_INET6)
+ fle6->f.n.next_hop6 =
+ ((struct sockaddr_in6 *)(rt->rt_gateway))->sin6_addr;
- if (rt_mask(rt))
- fle6->f.dst_mask = ipv6_masklen(((struct sockaddr_in6 *)rt_mask(rt))->sin6_addr);
- else
- fle6->f.dst_mask = 128;
+ if (rt_mask(rt))
+ fle6->f.dst_mask = RT_MASK6(rt);
+ else
+ fle6->f.dst_mask = 128;
- RTFREE_LOCKED(rt);
+ RTFREE_LOCKED(rt);
+ }
}
- /* Do route lookup on source address, to fill in src_mask. */
- bzero(&rin6, sizeof(struct route_in6));
- src = (struct sockaddr_in6 *)&rin6.ro_dst;
- src->sin6_len = sizeof(struct sockaddr_in6);
- src->sin6_family = AF_INET6;
- src->sin6_addr = r->src.r_src6;
+ if ((flags & NG_NETFLOW_CONF_NODSTLOOKUP) == 0)
+ {
+ /* Do route lookup on source address, to fill in src_mask. */
+ bzero(&rin6, sizeof(struct route_in6));
+ src = (struct sockaddr_in6 *)&rin6.ro_dst;
+ src->sin6_len = sizeof(struct sockaddr_in6);
+ src->sin6_family = AF_INET6;
+ src->sin6_addr = r->src.r_src6;
- rin6.ro_rt = rtalloc1_fib((struct sockaddr *)src, 0, 0, r->fib);
+ rin6.ro_rt = rtalloc1_fib((struct sockaddr *)src, 0, 0, r->fib);
- if (rin6.ro_rt != NULL) {
- rt = rin6.ro_rt;
+ if (rin6.ro_rt != NULL) {
+ rt = rin6.ro_rt;
- if (rt_mask(rt))
- fle6->f.src_mask = ipv6_masklen(((struct sockaddr_in6 *)rt_mask(rt))->sin6_addr);
- else
- fle6->f.src_mask = 128;
+ if (rt_mask(rt))
+ fle6->f.src_mask = RT_MASK6(rt);
+ else
+ fle6->f.src_mask = 128;
- RTFREE_LOCKED(rt);
+ RTFREE_LOCKED(rt);
+ }
}
/* Push new flow at the and of hash. */
@@ -495,6 +505,8 @@
return (0);
}
+#undef ipv6_masklen
+#undef RT_MASK6
#endif
@@ -651,7 +663,7 @@
/* Insert packet from into flow cache. */
int
ng_netflow_flow_add(priv_p priv, fib_export_p fe, struct ip *ip, caddr_t upper_ptr, uint8_t upper_proto,
- uint8_t is_frag, unsigned int src_if_index)
+ uint8_t flags, unsigned int src_if_index)
{
register struct flow_entry *fle, *fle1;
struct flow_hash_entry *hsh;
@@ -770,7 +782,7 @@
}
}
} else /* A new flow entry. */
- error = hash_insert(priv, hsh, &r, plen, tcp_flags);
+ error = hash_insert(priv, hsh, &r, plen, flags, tcp_flags);
mtx_unlock(&hsh->mtx);
@@ -781,7 +793,7 @@
/* Insert IPv6 packet from into flow cache. */
int
ng_netflow_flow6_add(priv_p priv, fib_export_p fe, struct ip6_hdr *ip6, caddr_t upper_ptr, uint8_t upper_proto,
- uint8_t is_frag, unsigned int src_if_index)
+ uint8_t flags, unsigned int src_if_index)
{
register struct flow_entry *fle = NULL, *fle1;
register struct flow6_entry *fle6;
@@ -811,7 +823,7 @@
#if 0
r.r_tos = ip->ip_tos;
#endif
- if (is_frag == 0) {
+ if ((flags & NG_NETFLOW_IS_FRAG) == 0) {
switch(upper_proto) {
case IPPROTO_TCP:
{
@@ -896,7 +908,7 @@
}
}
} else /* A new flow entry. */
- error = hash6_insert(priv, hsh, &r, plen, tcp_flags);
+ error = hash6_insert(priv, hsh, &r, plen, flags, tcp_flags);
mtx_unlock(&hsh->mtx);
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/netgraph/netflow/netflow_v9.c
--- a/head/sys/netgraph/netflow/netflow_v9.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/netgraph/netflow/netflow_v9.c Wed Jul 25 16:47:10 2012 +0300
@@ -23,11 +23,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: head/sys/netgraph/netflow/netflow_v9.c 223706 2011-07-01 08:27:03Z glebius $
+ * $FreeBSD: head/sys/netgraph/netflow/netflow_v9.c 237164 2012-06-16 13:55:31Z melifaro $
*/
static const char rcs_id[] =
- "@(#) $FreeBSD: head/sys/netgraph/netflow/netflow_v9.c 223706 2011-07-01 08:27:03Z glebius $";
+ "@(#) $FreeBSD: head/sys/netgraph/netflow/netflow_v9.c 237164 2012-06-16 13:55:31Z melifaro $";
#include "opt_inet6.h"
#include "opt_route.h"
@@ -222,7 +222,7 @@
header->unix_secs = htonl(ts.tv_sec);
header->seq_num = htonl(atomic_fetchadd_32(&fe->flow9_seq, 1));
header->count = htons(t->count);
- header->source_id = htonl(NG_NODE_ID(priv->node));
+ header->source_id = htonl(fe->domain_id);
if (priv->export9 != NULL)
NG_FWD_ITEM_HOOK_FLAGS(error, item, priv->export9, flags);
@@ -416,16 +416,14 @@
* Check if we need to insert templates into packet
*/
- struct timespec ts;
struct netflow_v9_flowset_header *fl;
- getnanotime(&ts);
- if ((ts.tv_sec >= priv->templ_time + fe->templ_last_ts) ||
+ if ((time_uptime >= priv->templ_time + fe->templ_last_ts) ||
(fe->sent_packets >= priv->templ_packets + fe->templ_last_pkt)) {
- atomic_store_rel_32(&fe->templ_last_ts, ts.tv_sec);
- atomic_store_rel_32(&fe->templ_last_pkt, fe->sent_packets);
-
+ fe->templ_last_ts = time_uptime;
+ fe->templ_last_pkt = fe->sent_packets;
+
fl = priv->v9_flowsets[0];
m_append(m, ntohs(fl->length), (void *)fl);
t->flow_header = m->m_len;
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/netgraph/netflow/ng_netflow.c
--- a/head/sys/netgraph/netflow/ng_netflow.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/netgraph/netflow/ng_netflow.c Wed Jul 25 16:47:10 2012 +0300
@@ -29,7 +29,7 @@
*/
static const char rcs_id[] =
- "@(#) $FreeBSD: head/sys/netgraph/netflow/ng_netflow.c 232921 2012-03-13 11:08:40Z melifaro $";
+ "@(#) $FreeBSD: head/sys/netgraph/netflow/ng_netflow.c 237227 2012-06-18 13:56:36Z melifaro $";
#include "opt_inet6.h"
#include "opt_route.h"
@@ -560,8 +560,8 @@
struct ip6_hdr *ip6 = NULL;
struct m_tag *mtag;
int pullup_len = 0, off;
- uint8_t upper_proto = 0, is_frag = 0;
- int error = 0, bypass = 0, acct = 0;
+ uint8_t acct = 0, bypass = 0, flags = 0, upper_proto = 0;
+ int error = 0, l3_off = 0;
unsigned int src_if_index;
caddr_t upper_ptr = NULL;
fib_export_p fe;
@@ -619,6 +619,9 @@
}
}
+ /* Import configuration flags related to flow creation */
+ flags = iface->info.conf & NG_NETFLOW_FLOW_FLAGS;
+
NGI_GET_M(item, m);
m_old = m;
@@ -666,6 +669,7 @@
M_CHECK(sizeof(struct ip));
eh = mtod(m, struct ether_header *);
ip = (struct ip *)(eh + 1);
+ l3_off = sizeof(struct ether_header);
break;
#ifdef INET6
case ETHERTYPE_IPV6:
@@ -676,6 +680,7 @@
M_CHECK(sizeof(struct ip6_hdr));
eh = mtod(m, struct ether_header *);
ip6 = (struct ip6_hdr *)(eh + 1);
+ l3_off = sizeof(struct ether_header);
break;
#endif
case ETHERTYPE_VLAN:
@@ -686,6 +691,7 @@
sizeof(struct ether_header));
evh = mtod(m, struct ether_vlan_header *);
etype = ntohs(evh->evl_proto);
+ l3_off = sizeof(struct ether_vlan_header);
if (etype == ETHERTYPE_IP) {
M_CHECK(sizeof(struct ip));
@@ -707,12 +713,13 @@
case DLT_RAW: /* IP packets */
M_CHECK(sizeof(struct ip));
ip = mtod(m, struct ip *);
+ /* l3_off is already zero */
#ifdef INET6
/* If INET6 is not defined IPv6 packets will be discarded in ng_netflow_flow_add() */
if (ip->ip_v == IP6VERSION) {
/* IPv6 packet */
ip = NULL;
- M_CHECK(sizeof(struct ip6_hdr));
+ M_CHECK(sizeof(struct ip6_hdr) - sizeof(struct ip));
ip6 = mtod(m, struct ip6_hdr *);
}
#endif
@@ -755,7 +762,7 @@
}
} else if (ip != NULL) {
/* Nothing to save except upper layer proto, since this is packet fragment */
- is_frag = 1;
+ flags |= NG_NETFLOW_IS_FRAG;
upper_proto = ip->ip_p;
if ((ip->ip_v != IPVERSION) ||
((ip->ip_hl << 2) < sizeof(struct ip)))
@@ -817,14 +824,17 @@
upper_proto = ip6f->ip6f_nxt;
hdr_off = sizeof(struct ip6_frag);
off += hdr_off;
- is_frag = 1;
+ flags |= NG_NETFLOW_IS_FRAG;
goto loopend;
#if 0
case IPPROTO_NONE:
goto loopend;
#endif
- /* Any unknow header (new extension or IPv6/IPv4 header for tunnels) */
+ /*
+ * Any unknow header (new extension or IPv6/IPv4
+ * header for tunnels) ends loop.
+ */
default:
goto loopend;
}
@@ -842,56 +852,11 @@
/* Just in case of real reallocation in M_CHECK() / m_pullup() */
if (m != m_old) {
atomic_fetchadd_32(&priv->info.nfinfo_realloc_mbuf, 1);
- ip = NULL;
- ip6 = NULL;
- switch (iface->info.ifinfo_dlt) {
- case DLT_EN10MB: /* Ethernet */
- {
- struct ether_header *eh;
-
- eh = mtod(m, struct ether_header *);
- switch (ntohs(eh->ether_type)) {
- case ETHERTYPE_IP:
- ip = (struct ip *)(eh + 1);
- break;
-#ifdef INET6
- case ETHERTYPE_IPV6:
- ip6 = (struct ip6_hdr *)(eh + 1);
- break;
-#endif
- case ETHERTYPE_VLAN:
- {
- struct ether_vlan_header *evh;
-
- evh = mtod(m, struct ether_vlan_header *);
- if (ntohs(evh->evl_proto) == ETHERTYPE_IP) {
- ip = (struct ip *)(evh + 1);
- break;
-#ifdef INET6
- } else if (ntohs(evh->evl_proto) == ETHERTYPE_IPV6) {
- ip6 = (struct ip6_hdr *)(evh + 1);
- break;
-#endif
- }
- }
- default:
- panic("ng_netflow entered deadcode");
- }
- break;
- }
- case DLT_RAW: /* IP packets */
- ip = mtod(m, struct ip *);
-#ifdef INET6
- if (ip->ip_v == IP6VERSION) {
- /* IPv6 packet */
- ip = NULL;
- ip6 = mtod(m, struct ip6_hdr *);
- }
-#endif
- break;
- default:
- panic("ng_netflow entered deadcode");
- }
+ /* Restore ip/ipv6 pointer */
+ if (ip != NULL)
+ ip = (struct ip *)(mtod(m, caddr_t) + l3_off);
+ else if (ip6 != NULL)
+ ip6 = (struct ip6_hdr *)(mtod(m, caddr_t) + l3_off);
}
upper_ptr = (caddr_t)(mtod(m, caddr_t) + off);
@@ -924,10 +889,10 @@
}
if (ip != NULL)
- error = ng_netflow_flow_add(priv, fe, ip, upper_ptr, upper_proto, is_frag, src_if_index);
+ error = ng_netflow_flow_add(priv, fe, ip, upper_ptr, upper_proto, flags, src_if_index);
#ifdef INET6
else if (ip6 != NULL)
- error = ng_netflow_flow6_add(priv, fe, ip6, upper_ptr, upper_proto, is_frag, src_if_index);
+ error = ng_netflow_flow6_add(priv, fe, ip6, upper_ptr, upper_proto, flags, src_if_index);
#endif
else
goto bypass;
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/netgraph/netflow/ng_netflow.h
--- a/head/sys/netgraph/netflow/ng_netflow.h Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/netgraph/netflow/ng_netflow.h Wed Jul 25 16:47:10 2012 +0300
@@ -26,7 +26,7 @@
* SUCH DAMAGE.
*
* $SourceForge: ng_netflow.h,v 1.26 2004/09/04 15:44:55 glebius Exp $
- * $FreeBSD: head/sys/netgraph/netflow/ng_netflow.h 232921 2012-03-13 11:08:40Z melifaro $
+ * $FreeBSD: head/sys/netgraph/netflow/ng_netflow.h 237227 2012-06-18 13:56:36Z melifaro $
*/
#ifndef _NG_NETFLOW_H_
@@ -111,10 +111,16 @@
uint32_t active_timeout; /* flow active timeout */
};
-#define NG_NETFLOW_CONF_INGRESS 1
-#define NG_NETFLOW_CONF_EGRESS 2
-#define NG_NETFLOW_CONF_ONCE 4
-#define NG_NETFLOW_CONF_THISONCE 8
+#define NG_NETFLOW_CONF_INGRESS 0x01 /* Account on ingress */
+#define NG_NETFLOW_CONF_EGRESS 0x02 /* Account on egress */
+#define NG_NETFLOW_CONF_ONCE 0x04 /* Add tag to account only once */
+#define NG_NETFLOW_CONF_THISONCE 0x08 /* Account once in current node */
+#define NG_NETFLOW_CONF_NOSRCLOOKUP 0x10 /* No radix lookup on src */
+#define NG_NETFLOW_CONF_NODSTLOOKUP 0x20 /* No radix lookup on dst */
+
+#define NG_NETFLOW_IS_FRAG 0x01
+#define NG_NETFLOW_FLOW_FLAGS (NG_NETFLOW_CONF_NOSRCLOOKUP|\
+ NG_NETFLOW_CONF_NODSTLOOKUP)
/* This structure is passed to NGM_NETFLOW_SETCONFIG */
struct ng_netflow_setconfig {
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/netgraph/ng_ksocket.c
--- a/head/sys/netgraph/ng_ksocket.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/netgraph/ng_ksocket.c Wed Jul 25 16:47:10 2012 +0300
@@ -37,7 +37,7 @@
*
* Author: Archie Cobbs <archie at freebsd.org>
*
- * $FreeBSD: head/sys/netgraph/ng_ksocket.c 229272 2012-01-02 12:12:10Z ed $
+ * $FreeBSD: head/sys/netgraph/ng_ksocket.c 235923 2012-05-24 18:22:57Z glebius $
* $Whistle: ng_ksocket.c,v 1.1 1999/11/16 20:04:40 archie Exp $
*/
@@ -524,7 +524,9 @@
priv_p priv;
/* Allocate private structure */
- priv = malloc(sizeof(*priv), M_NETGRAPH_KSOCKET, M_WAITOK | M_ZERO);
+ priv = malloc(sizeof(*priv), M_NETGRAPH_KSOCKET, M_NOWAIT | M_ZERO);
+ if (priv == NULL)
+ return (ENOMEM);
LIST_INIT(&priv->embryos);
/* cross link them */
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/netgraph/ng_mppc.c
--- a/head/sys/netgraph/ng_mppc.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/netgraph/ng_mppc.c Wed Jul 25 16:47:10 2012 +0300
@@ -38,7 +38,7 @@
* Author: Archie Cobbs <archie at freebsd.org>
*
* $Whistle: ng_mppc.c,v 1.4 1999/11/25 00:10:12 archie Exp $
- * $FreeBSD: head/sys/netgraph/ng_mppc.c 227293 2011-11-07 06:44:47Z ed $
+ * $FreeBSD: head/sys/netgraph/ng_mppc.c 235979 2012-05-25 07:46:24Z glebius $
*/
/*
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/netgraph/ng_patch.c
--- a/head/sys/netgraph/ng_patch.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/netgraph/ng_patch.c Wed Jul 25 16:47:10 2012 +0300
@@ -26,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netgraph/ng_patch.c 220767 2011-04-18 09:10:27Z ae $");
+__FBSDID("$FreeBSD: head/sys/netgraph/ng_patch.c 234574 2012-04-22 17:00:52Z melifaro $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -517,7 +517,7 @@
return (ENOMEM);
}
do_patch(priv, m);
- m->m_flags |= priv->config->csum_flags;
+ m->m_pkthdr.csum_flags |= priv->config->csum_flags;
}
target = NULL;
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/netinet6/frag6.c
--- a/head/sys/netinet6/frag6.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/netinet6/frag6.c Wed Jul 25 16:47:10 2012 +0300
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/netinet6/frag6.c 238248 2012-07-08 15:30:24Z bz $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -221,6 +221,19 @@
/* offset now points to data portion */
offset += sizeof(struct ip6_frag);
+ /*
+ * XXX-BZ RFC XXXX (draft-gont-6man-ipv6-atomic-fragments)
+ * Handle "atomic" fragments (offset and m bit set to 0) upfront,
+ * unrelated to any reassembly. Just skip the fragment header.
+ */
+ if ((ip6f->ip6f_offlg & ~IP6F_RESERVED_MASK) == 0) {
+ /* XXX-BZ we want dedicated counters for this. */
+ V_ip6stat.ip6s_reassembled++;
+ in6_ifstat_inc(dstifp, ifs6_reass_ok);
+ *offp = offset;
+ return (ip6f->ip6f_nxt);
+ }
+
IP6Q_LOCK();
/*
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/netinet6/icmp6.c
--- a/head/sys/netinet6/icmp6.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/netinet6/icmp6.c Wed Jul 25 16:47:10 2012 +0300
@@ -61,7 +61,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet6/icmp6.c 231852 2012-02-17 02:39:58Z bz $");
+__FBSDID("$FreeBSD: head/sys/netinet6/icmp6.c 235953 2012-05-25 01:42:48Z bz $");
#include "opt_inet.h"
#include "opt_inet6.h"
@@ -2418,23 +2418,23 @@
if (rt) {
if (rt->rt_gateway == NULL ||
rt->rt_gateway->sa_family != AF_INET6) {
+ RTFREE_LOCKED(rt);
nd6log((LOG_ERR,
"ICMP6 redirect rejected; no route "
"with inet6 gateway found for redirect dst: %s\n",
icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
- RTFREE_LOCKED(rt);
goto bad;
}
gw6 = &(((struct sockaddr_in6 *)rt->rt_gateway)->sin6_addr);
if (bcmp(&src6, gw6, sizeof(struct in6_addr)) != 0) {
+ RTFREE_LOCKED(rt);
nd6log((LOG_ERR,
"ICMP6 redirect rejected; "
"not equal to gw-for-src=%s (must be same): "
"%s\n",
ip6_sprintf(ip6buf, gw6),
icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
- RTFREE_LOCKED(rt);
goto bad;
}
} else {
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/netinet6/in6.c
--- a/head/sys/netinet6/in6.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/netinet6/in6.c Wed Jul 25 16:47:10 2012 +0300
@@ -61,7 +61,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet6/in6.c 232054 2012-02-23 18:21:37Z kmacy $");
+__FBSDID("$FreeBSD: head/sys/netinet6/in6.c 238222 2012-07-08 08:49:37Z bz $");
#include "opt_compat.h"
#include "opt_inet.h"
@@ -1330,6 +1330,7 @@
struct sockaddr_in6 mltaddr, mltmask;
struct in6_multi_mship *imm;
struct rtentry *rt;
+ struct sockaddr_in6 sin6;
int error;
/*
@@ -1356,6 +1357,21 @@
if ((error = in6_setscope(&mltaddr.sin6_addr, ifp, NULL)) != 0)
return (error);
+ /*
+ * As for the mltaddr above, proactively prepare the sin6 to avoid
+ * rtentry un- and re-locking.
+ */
+ if (ifa0 != NULL) {
+ bzero(&sin6, sizeof(sin6));
+ sin6.sin6_len = sizeof(sin6);
+ sin6.sin6_family = AF_INET6;
+ memcpy(&sin6.sin6_addr, &satosin6(ifa0->ifa_addr)->sin6_addr,
+ sizeof(sin6.sin6_addr));
+ error = in6_setscope(&sin6.sin6_addr, ifa0->ifa_ifp, NULL);
+ if (error != 0)
+ return (error);
+ }
+
rt = in6_rtalloc1((struct sockaddr *)&mltaddr, 0, 0UL, RT_DEFAULT_FIB);
if (rt != NULL && rt->rt_gateway != NULL &&
(memcmp(&satosin6(rt->rt_gateway)->sin6_addr,
@@ -1382,15 +1398,7 @@
/*
* Replace the gateway of the route.
*/
- struct sockaddr_in6 sa;
-
- bzero(&sa, sizeof(sa));
- sa.sin6_len = sizeof(struct sockaddr_in6);
- sa.sin6_family = AF_INET6;
- memcpy(&sa.sin6_addr, &satosin6(ifa0->ifa_addr)->sin6_addr,
- sizeof(sa.sin6_addr));
- in6_setscope(&sa.sin6_addr, ifa0->ifa_ifp, NULL);
- memcpy(rt->rt_gateway, &sa, sizeof(sa));
+ memcpy(rt->rt_gateway, &sin6, sizeof(sin6));
RTFREE_LOCKED(rt);
}
} else {
@@ -1432,15 +1440,7 @@
/*
* Replace the gateway of the route.
*/
- struct sockaddr_in6 sa;
-
- bzero(&sa, sizeof(sa));
- sa.sin6_len = sizeof(struct sockaddr_in6);
- sa.sin6_family = AF_INET6;
- memcpy(&sa.sin6_addr, &satosin6(ifa0->ifa_addr)->sin6_addr,
- sizeof(sa.sin6_addr));
- in6_setscope(&sa.sin6_addr, ifa0->ifa_ifp, NULL);
- memcpy(rt->rt_gateway, &sa, sizeof(sa));
+ memcpy(rt->rt_gateway, &sin6, sizeof(sin6));
RTFREE_LOCKED(rt);
}
} else {
@@ -1667,14 +1667,19 @@
hostid = IFA_IN6(ifa);
/* prefixlen must be <= 64. */
- if (64 < iflr->prefixlen)
+ if (64 < iflr->prefixlen) {
+ if (ifa != NULL)
+ ifa_free(ifa);
return EINVAL;
+ }
prefixlen = iflr->prefixlen;
/* hostid part must be zero. */
sin6 = (struct sockaddr_in6 *)&iflr->addr;
if (sin6->sin6_addr.s6_addr32[2] != 0 ||
sin6->sin6_addr.s6_addr32[3] != 0) {
+ if (ifa != NULL)
+ ifa_free(ifa);
return EINVAL;
}
} else
@@ -2265,14 +2270,20 @@
IF_ADDR_RUNLOCK(ifp);
return (struct in6_ifaddr *)ifa;
}
- IF_ADDR_RUNLOCK(ifp);
/* use the last-resort values, that are, deprecated addresses */
- if (dep[0])
+ if (dep[0]) {
+ ifa_ref((struct ifaddr *)dep[0]);
+ IF_ADDR_RUNLOCK(ifp);
return dep[0];
- if (dep[1])
+ }
+ if (dep[1]) {
+ ifa_ref((struct ifaddr *)dep[1]);
+ IF_ADDR_RUNLOCK(ifp);
return dep[1];
+ }
+ IF_ADDR_RUNLOCK(ifp);
return NULL;
}
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/netinet6/in6.h
--- a/head/sys/netinet6/in6.h Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/netinet6/in6.h Wed Jul 25 16:47:10 2012 +0300
@@ -58,7 +58,7 @@
* SUCH DAMAGE.
*
* @(#)in.h 8.3 (Berkeley) 1/3/94
- * $FreeBSD: head/sys/netinet6/in6.h 230584 2012-01-26 12:04:19Z glebius $
+ * $FreeBSD: head/sys/netinet6/in6.h 235924 2012-05-24 18:25:09Z bz $
*/
#ifndef __KAME_NETINET_IN_H_INCLUDED_
@@ -632,7 +632,9 @@
#ifdef _KERNEL
struct cmsghdr;
+struct ip6_hdr;
+int in6_cksum_pseudo(struct ip6_hdr *, uint32_t, uint8_t, uint16_t);
int in6_cksum __P((struct mbuf *, u_int8_t, u_int32_t, u_int32_t));
int in6_localaddr __P((struct in6_addr *));
int in6_localip(struct in6_addr *);
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/netinet6/in6_cksum.c
--- a/head/sys/netinet6/in6_cksum.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/netinet6/in6_cksum.c Wed Jul 25 16:47:10 2012 +0300
@@ -61,7 +61,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/netinet6/in6_cksum.c 235924 2012-05-24 18:25:09Z bz $");
#include <sys/param.h>
#include <sys/mbuf.h>
@@ -80,6 +80,66 @@
#define ADDCARRY(x) (x > 65535 ? x -= 65535 : x)
#define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; (void)ADDCARRY(sum);}
+static int
+_in6_cksum_pseudo(struct ip6_hdr *ip6, uint32_t len, uint8_t nxt, uint16_t csum)
+{
+ int sum;
+ uint16_t scope, *w;
+ union {
+ u_int16_t phs[4];
+ struct {
+ u_int32_t ph_len;
+ u_int8_t ph_zero[3];
+ u_int8_t ph_nxt;
+ } __packed ph;
+ } uph;
+
+ sum = csum;
+
+ /*
+ * First create IP6 pseudo header and calculate a summary.
+ */
+ uph.ph.ph_len = htonl(len);
+ uph.ph.ph_zero[0] = uph.ph.ph_zero[1] = uph.ph.ph_zero[2] = 0;
+ uph.ph.ph_nxt = nxt;
+
+ /* Payload length and upper layer identifier. */
+ sum += uph.phs[0]; sum += uph.phs[1];
+ sum += uph.phs[2]; sum += uph.phs[3];
+
+ /* IPv6 source address. */
+ scope = in6_getscope(&ip6->ip6_src);
+ w = (u_int16_t *)&ip6->ip6_src;
+ sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
+ sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
+ if (scope != 0)
+ sum -= scope;
+
+ /* IPv6 destination address. */
+ scope = in6_getscope(&ip6->ip6_dst);
+ w = (u_int16_t *)&ip6->ip6_dst;
+ sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
+ sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
+ if (scope != 0)
+ sum -= scope;
+
+ return (sum);
+}
+
+int
+in6_cksum_pseudo(struct ip6_hdr *ip6, uint32_t len, uint8_t nxt, uint16_t csum)
+{
+ int sum;
+ union {
+ u_int16_t s[2];
+ u_int32_t l;
+ } l_util;
+
+ sum = _in6_cksum_pseudo(ip6, len, nxt, csum);
+ REDUCE;
+ return (sum);
+}
+
/*
* m MUST contain a contiguous IP6 header.
* off is an offset where TCP/UDP/ICMP6 header starts.
@@ -89,12 +149,10 @@
int
in6_cksum(struct mbuf *m, u_int8_t nxt, u_int32_t off, u_int32_t len)
{
- u_int16_t *w;
- int sum = 0;
- int mlen = 0;
- int byte_swapped = 0;
struct ip6_hdr *ip6;
- struct in6_addr in6;
+ u_int16_t *w, scope;
+ int byte_swapped, mlen;
+ int sum;
union {
u_int16_t phs[4];
struct {
@@ -112,42 +170,38 @@
u_int32_t l;
} l_util;
- /* sanity check */
- if (m->m_pkthdr.len < off + len) {
- panic("in6_cksum: mbuf len (%d) < off+len (%d+%d)",
- m->m_pkthdr.len, off, len);
- }
-
- bzero(&uph, sizeof(uph));
+ /* Sanity check. */
+ KASSERT(m->m_pkthdr.len >= off + len, ("%s: mbuf len (%d) < off(%d)+"
+ "len(%d)", __func__, m->m_pkthdr.len, off, len));
/*
* First create IP6 pseudo header and calculate a summary.
*/
- ip6 = mtod(m, struct ip6_hdr *);
uph.ph.ph_len = htonl(len);
+ uph.ph.ph_zero[0] = uph.ph.ph_zero[1] = uph.ph.ph_zero[2] = 0;
uph.ph.ph_nxt = nxt;
- /*
- * IPv6 source address.
- * XXX: we'd like to avoid copying the address, but we can't due to
- * the possibly embedded scope zone ID.
- */
- in6 = ip6->ip6_src;
- in6_clearscope(&in6);
- w = (u_int16_t *)&in6;
+ /* Payload length and upper layer identifier. */
+ sum = uph.phs[0]; sum += uph.phs[1];
+ sum += uph.phs[2]; sum += uph.phs[3];
+
+ ip6 = mtod(m, struct ip6_hdr *);
+
+ /* IPv6 source address. */
+ scope = in6_getscope(&ip6->ip6_src);
+ w = (u_int16_t *)&ip6->ip6_src;
sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
+ if (scope != 0)
+ sum -= scope;
- /* IPv6 destination address */
- in6 = ip6->ip6_dst;
- in6_clearscope(&in6);
- w = (u_int16_t *)&in6;
+ /* IPv6 destination address. */
+ scope = in6_getscope(&ip6->ip6_dst);
+ w = (u_int16_t *)&ip6->ip6_dst;
sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
-
- /* Payload length and upper layer identifier */
- sum += uph.phs[0]; sum += uph.phs[1];
- sum += uph.phs[2]; sum += uph.phs[3];
+ if (scope != 0)
+ sum -= scope;
/*
* Secondly calculate a summary of the first mbuf excluding offset.
@@ -167,14 +221,16 @@
/*
* Force to even boundary.
*/
- if ((1 & (long) w) && (mlen > 0)) {
+ if ((1 & (long)w) && (mlen > 0)) {
REDUCE;
sum <<= 8;
s_util.c[0] = *(u_char *)w;
w = (u_int16_t *)((char *)w + 1);
mlen--;
byte_swapped = 1;
- }
+ } else
+ byte_swapped = 0;
+
/*
* Unroll the loop to make overhead from
* branches &c small.
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/netinet6/in6_src.c
--- a/head/sys/netinet6/in6_src.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/netinet6/in6_src.c Wed Jul 25 16:47:10 2012 +0300
@@ -61,7 +61,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet6/in6_src.c 232127 2012-02-24 20:06:04Z bz $");
+__FBSDID("$FreeBSD: head/sys/netinet6/in6_src.c 237459 2012-06-22 21:26:35Z bz $");
#include "opt_inet.h"
#include "opt_inet6.h"
@@ -597,6 +597,7 @@
if (ron->ro_rt == NULL) {
in6_rtalloc(ron, fibnum); /* multi path case? */
if (ron->ro_rt == NULL) {
+ /* XXX-BZ WT.? */
if (ron->ro_rt) {
RTFREE(ron->ro_rt);
ron->ro_rt = NULL;
@@ -873,8 +874,7 @@
RTFREE(ro6.ro_rt);
if (lifp)
return (ND_IFINFO(lifp)->chlim);
- } else
- return (V_ip6_defhlim);
+ }
}
return (V_ip6_defhlim);
}
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/netinet6/ip6_forward.c
--- a/head/sys/netinet6/ip6_forward.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/netinet6/ip6_forward.c Wed Jul 25 16:47:10 2012 +0300
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet6/ip6_forward.c 231852 2012-02-17 02:39:58Z bz $");
+__FBSDID("$FreeBSD: head/sys/netinet6/ip6_forward.c 236332 2012-05-30 20:56:07Z tuexen $");
#include "opt_inet.h"
#include "opt_inet6.h"
@@ -581,15 +581,13 @@
m->m_flags |= M_FASTFWD_OURS;
if (m->m_pkthdr.rcvif == NULL)
m->m_pkthdr.rcvif = V_loif;
- if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
+ if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA_IPV6) {
m->m_pkthdr.csum_flags |=
- CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
+ CSUM_DATA_VALID_IPV6 | CSUM_PSEUDO_HDR;
m->m_pkthdr.csum_data = 0xffff;
}
- m->m_pkthdr.csum_flags |=
- CSUM_IP_CHECKED | CSUM_IP_VALID;
#ifdef SCTP
- if (m->m_pkthdr.csum_flags & CSUM_SCTP)
+ if (m->m_pkthdr.csum_flags & CSUM_SCTP_IPV6)
m->m_pkthdr.csum_flags |= CSUM_SCTP_VALID;
#endif
error = netisr_queue(NETISR_IPV6, m);
@@ -603,15 +601,15 @@
if (m->m_flags & M_FASTFWD_OURS) {
if (m->m_pkthdr.rcvif == NULL)
m->m_pkthdr.rcvif = V_loif;
- if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
+ if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA_IPV6) {
m->m_pkthdr.csum_flags |=
- CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
+ CSUM_DATA_VALID_IPV6 | CSUM_PSEUDO_HDR;
m->m_pkthdr.csum_data = 0xffff;
}
#ifdef SCTP
- if (m->m_pkthdr.csum_flags & CSUM_SCTP)
- m->m_pkthdr.csum_flags |= CSUM_SCTP_VALID;
-#endif
+ if (m->m_pkthdr.csum_flags & CSUM_SCTP_IPV6)
+ m->m_pkthdr.csum_flags |= CSUM_SCTP_VALID;
+#endif
error = netisr_queue(NETISR_IPV6, m);
goto out;
}
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/netinet6/ip6_input.c
--- a/head/sys/netinet6/ip6_input.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/netinet6/ip6_input.c Wed Jul 25 16:47:10 2012 +0300
@@ -61,7 +61,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet6/ip6_input.c 232379 2012-03-02 07:23:28Z hrs $");
+__FBSDID("$FreeBSD: head/sys/netinet6/ip6_input.c 236958 2012-06-12 13:57:56Z tuexen $");
#include "opt_inet.h"
#include "opt_inet6.h"
@@ -146,6 +146,9 @@
static void ip6_init2(void *);
static struct ip6aux *ip6_setdstifaddr(struct mbuf *, struct in6_ifaddr *);
+static struct ip6aux *ip6_addaux(struct mbuf *);
+static struct ip6aux *ip6_findaux(struct mbuf *m);
+static void ip6_delaux (struct mbuf *);
static int ip6_hopopts_input(u_int32_t *, u_int32_t *, struct mbuf **, int *);
#ifdef PULLDOWN_TEST
static struct mbuf *ip6_pullexthdr(struct mbuf *, size_t, int);
@@ -328,6 +331,83 @@
/* This must be after route_init(), which is now SI_ORDER_THIRD */
SYSINIT(netinet6init2, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, ip6_init2, NULL);
+static int
+ip6_input_hbh(struct mbuf *m, uint32_t *plen, uint32_t *rtalert, int *off,
+ int *nxt, int *ours)
+{
+ struct ip6_hdr *ip6;
+ struct ip6_hbh *hbh;
+
+ if (ip6_hopopts_input(plen, rtalert, &m, off)) {
+#if 0 /*touches NULL pointer*/
+ in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
+#endif
+ goto out; /* m have already been freed */
+ }
+
+ /* adjust pointer */
+ ip6 = mtod(m, struct ip6_hdr *);
+
+ /*
+ * if the payload length field is 0 and the next header field
+ * indicates Hop-by-Hop Options header, then a Jumbo Payload
+ * option MUST be included.
+ */
+ if (ip6->ip6_plen == 0 && *plen == 0) {
+ /*
+ * Note that if a valid jumbo payload option is
+ * contained, ip6_hopopts_input() must set a valid
+ * (non-zero) payload length to the variable plen.
+ */
+ V_ip6stat.ip6s_badoptions++;
+ in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
+ in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr);
+ icmp6_error(m, ICMP6_PARAM_PROB,
+ ICMP6_PARAMPROB_HEADER,
+ (caddr_t)&ip6->ip6_plen - (caddr_t)ip6);
+ goto out;
+ }
+#ifndef PULLDOWN_TEST
+ /* ip6_hopopts_input() ensures that mbuf is contiguous */
+ hbh = (struct ip6_hbh *)(ip6 + 1);
+#else
+ IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr),
+ sizeof(struct ip6_hbh));
+ if (hbh == NULL) {
+ V_ip6stat.ip6s_tooshort++;
+ goto out;
+ }
+#endif
+ *nxt = hbh->ip6h_nxt;
+
+ /*
+ * If we are acting as a router and the packet contains a
+ * router alert option, see if we know the option value.
+ * Currently, we only support the option value for MLD, in which
+ * case we should pass the packet to the multicast routing
+ * daemon.
+ */
+ if (*rtalert != ~0) {
+ switch (*rtalert) {
+ case IP6OPT_RTALERT_MLD:
+ if (V_ip6_forwarding)
+ *ours = 1;
+ break;
+ default:
+ /*
+ * RFC2711 requires unrecognized values must be
+ * silently ignored.
+ */
+ break;
+ }
+ }
+
+ return (0);
+
+out:
+ return (1);
+}
+
void
ip6_input(struct mbuf *m)
{
@@ -799,19 +879,23 @@
* as our interface address (e.g. multicast addresses, addresses
* within FAITH prefixes and such).
*/
- if (deliverifp && !ip6_getdstifaddr(m)) {
+ if (deliverifp) {
struct in6_ifaddr *ia6;
- ia6 = in6_ifawithifp(deliverifp, &ip6->ip6_dst);
- if (ia6) {
- if (!ip6_setdstifaddr(m, ia6)) {
- /*
- * XXX maybe we should drop the packet here,
- * as we could not provide enough information
- * to the upper layers.
- */
+ if ((ia6 = ip6_getdstifaddr(m)) != NULL) {
+ ifa_free(&ia6->ia_ifa);
+ } else {
+ ia6 = in6_ifawithifp(deliverifp, &ip6->ip6_dst);
+ if (ia6) {
+ if (!ip6_setdstifaddr(m, ia6)) {
+ /*
+ * XXX maybe we should drop the packet here,
+ * as we could not provide enough information
+ * to the upper layers.
+ */
+ }
+ ifa_free(&ia6->ia_ifa);
}
- ifa_free(&ia6->ia_ifa);
}
}
@@ -822,71 +906,11 @@
*/
plen = (u_int32_t)ntohs(ip6->ip6_plen);
if (ip6->ip6_nxt == IPPROTO_HOPOPTS) {
- struct ip6_hbh *hbh;
+ int error;
- if (ip6_hopopts_input(&plen, &rtalert, &m, &off)) {
-#if 0 /*touches NULL pointer*/
- in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
-#endif
- goto out; /* m have already been freed */
- }
-
- /* adjust pointer */
- ip6 = mtod(m, struct ip6_hdr *);
-
- /*
- * if the payload length field is 0 and the next header field
- * indicates Hop-by-Hop Options header, then a Jumbo Payload
- * option MUST be included.
- */
- if (ip6->ip6_plen == 0 && plen == 0) {
- /*
- * Note that if a valid jumbo payload option is
- * contained, ip6_hopopts_input() must set a valid
- * (non-zero) payload length to the variable plen.
- */
- V_ip6stat.ip6s_badoptions++;
- in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
- in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr);
- icmp6_error(m, ICMP6_PARAM_PROB,
- ICMP6_PARAMPROB_HEADER,
- (caddr_t)&ip6->ip6_plen - (caddr_t)ip6);
+ error = ip6_input_hbh(m, &plen, &rtalert, &off, &nxt, &ours);
+ if (error != 0)
goto out;
- }
-#ifndef PULLDOWN_TEST
- /* ip6_hopopts_input() ensures that mbuf is contiguous */
- hbh = (struct ip6_hbh *)(ip6 + 1);
-#else
- IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr),
- sizeof(struct ip6_hbh));
- if (hbh == NULL) {
- V_ip6stat.ip6s_tooshort++;
- goto out;
- }
-#endif
- nxt = hbh->ip6h_nxt;
-
- /*
- * If we are acting as a router and the packet contains a
- * router alert option, see if we know the option value.
- * Currently, we only support the option value for MLD, in which
- * case we should pass the packet to the multicast routing
- * daemon.
- */
- if (rtalert != ~0) {
- switch (rtalert) {
- case IP6OPT_RTALERT_MLD:
- if (V_ip6_forwarding)
- ours = 1;
- break;
- default:
- /*
- * RFC2711 requires unrecognized values must be
- * silently ignored.
- */
- break;
- }
- }
} else
nxt = ip6->ip6_nxt;
@@ -1297,19 +1321,28 @@
}
#endif
- if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
- if (v4only != NULL)
- *v4only = 1;
- return (mp);
- }
-
#define IS2292(inp, x, y) (((inp)->inp_flags & IN6P_RFC2292) ? (x) : (y))
/* RFC 2292 sec. 5 */
if ((inp->inp_flags & IN6P_PKTINFO) != 0) {
struct in6_pktinfo pi6;
- bcopy(&ip6->ip6_dst, &pi6.ipi6_addr, sizeof(struct in6_addr));
- in6_clearscope(&pi6.ipi6_addr); /* XXX */
+ if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
+#ifdef INET
+ struct ip *ip;
+
+ ip = mtod(m, struct ip *);
+ pi6.ipi6_addr.s6_addr32[0] = 0;
+ pi6.ipi6_addr.s6_addr32[1] = 0;
+ pi6.ipi6_addr.s6_addr32[2] = IPV6_ADDR_INT32_SMP;
+ pi6.ipi6_addr.s6_addr32[3] = ip->ip_dst.s_addr;
+#else
+ /* We won't hit this code */
+ bzero(&pi6.ipi6_addr, sizeof(struct in6_addr));
+#endif
+ } else {
+ bcopy(&ip6->ip6_dst, &pi6.ipi6_addr, sizeof(struct in6_addr));
+ in6_clearscope(&pi6.ipi6_addr); /* XXX */
+ }
pi6.ipi6_ifindex =
(m && m->m_pkthdr.rcvif) ? m->m_pkthdr.rcvif->if_index : 0;
@@ -1321,8 +1354,21 @@
}
if ((inp->inp_flags & IN6P_HOPLIMIT) != 0) {
- int hlim = ip6->ip6_hlim & 0xff;
+ int hlim;
+ if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
+#ifdef INET
+ struct ip *ip;
+
+ ip = mtod(m, struct ip *);
+ hlim = ip->ip_ttl;
+#else
+ /* We won't hit this code */
+ hlim = 0;
+#endif
+ } else {
+ hlim = ip6->ip6_hlim & 0xff;
+ }
*mp = sbcreatecontrol((caddr_t) &hlim, sizeof(int),
IS2292(inp, IPV6_2292HOPLIMIT, IPV6_HOPLIMIT),
IPPROTO_IPV6);
@@ -1330,8 +1376,40 @@
mp = &(*mp)->m_next;
}
- if (v4only != NULL)
- *v4only = 0;
+ if ((inp->inp_flags & IN6P_TCLASS) != 0) {
+ int tclass;
+
+ if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
+#ifdef INET
+ struct ip *ip;
+
+ ip = mtod(m, struct ip *);
+ tclass = ip->ip_tos;
+#else
+ /* We won't hit this code */
+ tclass = 0;
+#endif
+ } else {
+ u_int32_t flowinfo;
+
+ flowinfo = (u_int32_t)ntohl(ip6->ip6_flow & IPV6_FLOWINFO_MASK);
+ flowinfo >>= 20;
+ tclass = flowinfo & 0xff;
+ }
+ *mp = sbcreatecontrol((caddr_t) &tclass, sizeof(int),
+ IPV6_TCLASS, IPPROTO_IPV6);
+ if (*mp)
+ mp = &(*mp)->m_next;
+ }
+
+ if (v4only != NULL) {
+ if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
+ *v4only = 1;
+ } else {
+ *v4only = 0;
+ }
+ }
+
return (mp);
}
@@ -1345,20 +1423,6 @@
if (v4only)
return;
- if ((in6p->inp_flags & IN6P_TCLASS) != 0) {
- u_int32_t flowinfo;
- int tclass;
-
- flowinfo = (u_int32_t)ntohl(ip6->ip6_flow & IPV6_FLOWINFO_MASK);
- flowinfo >>= 20;
-
- tclass = flowinfo & 0xff;
- *mp = sbcreatecontrol((caddr_t) &tclass, sizeof(tclass),
- IPV6_TCLASS, IPPROTO_IPV6);
- if (*mp)
- mp = &(*mp)->m_next;
- }
-
/*
* IPV6_HOPOPTS socket option. Recall that we required super-user
* privilege for the option (see ip6_ctloutput), but it might be too
@@ -1772,7 +1836,7 @@
}
}
-struct ip6aux *
+static struct ip6aux *
ip6_addaux(struct mbuf *m)
{
struct m_tag *mtag;
@@ -1789,7 +1853,7 @@
return mtag ? (struct ip6aux *)(mtag + 1) : NULL;
}
-struct ip6aux *
+static struct ip6aux *
ip6_findaux(struct mbuf *m)
{
struct m_tag *mtag;
@@ -1798,7 +1862,7 @@
return mtag ? (struct ip6aux *)(mtag + 1) : NULL;
}
-void
+static void
ip6_delaux(struct mbuf *m)
{
struct m_tag *mtag;
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/netinet6/ip6_ipsec.c
--- a/head/sys/netinet6/ip6_ipsec.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/netinet6/ip6_ipsec.c Wed Jul 25 16:47:10 2012 +0300
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet6/ip6_ipsec.c 230442 2012-01-22 02:13:19Z bz $");
+__FBSDID("$FreeBSD: head/sys/netinet6/ip6_ipsec.c 236170 2012-05-28 09:30:13Z bz $");
#include "opt_inet.h"
#include "opt_inet6.h"
@@ -291,6 +291,7 @@
/*
* Do delayed checksums now because we send before
* this is done in the normal processing path.
+ * XXX-BZ CSUM_DELAY_DATA_IPV6?
*/
if ((*m)->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
ipseclog((LOG_DEBUG,
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/netinet6/ip6_mroute.c
--- a/head/sys/netinet6/ip6_mroute.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/netinet6/ip6_mroute.c Wed Jul 25 16:47:10 2012 +0300
@@ -79,7 +79,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet6/ip6_mroute.c 228700 2011-12-19 05:50:34Z maxim $");
+__FBSDID("$FreeBSD: head/sys/netinet6/ip6_mroute.c 238016 2012-07-02 19:44:18Z glebius $");
#include "opt_inet.h"
#include "opt_inet6.h"
@@ -717,7 +717,6 @@
mifp->m6_pkt_out = 0;
mifp->m6_bytes_in = 0;
mifp->m6_bytes_out = 0;
- bzero(&mifp->m6_route, sizeof(mifp->m6_route));
/* Adjust nummifs up if the mifi is higher than nummifs */
if (nummifs <= mifcp->mif6c_mifi)
@@ -1576,11 +1575,8 @@
struct mbuf *mb_copy;
struct ifnet *ifp = mifp->m6_ifp;
int error = 0;
- struct sockaddr_in6 *dst6;
u_long linkmtu;
- dst6 = &mifp->m6_route.ro_dst;
-
/*
* Make a new reference to the packet; make sure that
* the IPv6 header is actually copied, not just referenced,
@@ -1610,8 +1606,8 @@
/* XXX: ip6_output will override ip6->ip6_hlim */
im6o.im6o_multicast_hlim = ip6->ip6_hlim;
im6o.im6o_multicast_loop = 1;
- error = ip6_output(mb_copy, NULL, &mifp->m6_route,
- IPV6_FORWARDING, &im6o, NULL, NULL);
+ error = ip6_output(mb_copy, NULL, NULL, IPV6_FORWARDING, &im6o,
+ NULL, NULL);
#ifdef MRT6DEBUG
if (V_mrt6debug & DEBUG_XMIT)
@@ -1626,10 +1622,13 @@
* loop back a copy now.
*/
if (in6_mcast_loop) {
- dst6->sin6_len = sizeof(struct sockaddr_in6);
- dst6->sin6_family = AF_INET6;
- dst6->sin6_addr = ip6->ip6_dst;
- ip6_mloopback(ifp, m, &mifp->m6_route.ro_dst);
+ struct sockaddr_in6 dst6;
+
+ bzero(&dst6, sizeof(dst6));
+ dst6.sin6_len = sizeof(struct sockaddr_in6);
+ dst6.sin6_family = AF_INET6;
+ dst6.sin6_addr = ip6->ip6_dst;
+ ip6_mloopback(ifp, m, &dst6);
}
/*
@@ -1638,15 +1637,18 @@
*/
linkmtu = IN6_LINKMTU(ifp);
if (mb_copy->m_pkthdr.len <= linkmtu || linkmtu < IPV6_MMTU) {
- dst6->sin6_len = sizeof(struct sockaddr_in6);
- dst6->sin6_family = AF_INET6;
- dst6->sin6_addr = ip6->ip6_dst;
+ struct sockaddr_in6 dst6;
+
+ bzero(&dst6, sizeof(dst6));
+ dst6.sin6_len = sizeof(struct sockaddr_in6);
+ dst6.sin6_family = AF_INET6;
+ dst6.sin6_addr = ip6->ip6_dst;
/*
* We just call if_output instead of nd6_output here, since
* we need no ND for a multicast forwarded packet...right?
*/
error = (*ifp->if_output)(ifp, mb_copy,
- (struct sockaddr *)&mifp->m6_route.ro_dst, NULL);
+ (struct sockaddr *)&dst6, NULL);
#ifdef MRT6DEBUG
if (V_mrt6debug & DEBUG_XMIT)
log(LOG_DEBUG, "phyint_send on mif %d err %d\n",
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/netinet6/ip6_mroute.h
--- a/head/sys/netinet6/ip6_mroute.h Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/netinet6/ip6_mroute.h Wed Jul 25 16:47:10 2012 +0300
@@ -27,7 +27,7 @@
* SUCH DAMAGE.
*
* $KAME: ip6_mroute.h,v 1.19 2001/06/14 06:12:55 suz Exp $
- * $FreeBSD$
+ * $FreeBSD: head/sys/netinet6/ip6_mroute.h 238016 2012-07-02 19:44:18Z glebius $
*/
/* BSDI ip_mroute.h,v 2.5 1996/10/11 16:01:48 pjd Exp */
@@ -212,7 +212,6 @@
u_quad_t m6_pkt_out; /* # pkts out on interface */
u_quad_t m6_bytes_in; /* # bytes in on interface */
u_quad_t m6_bytes_out; /* # bytes out on interface */
- struct route_in6 m6_route; /* cached route */
#ifdef notyet
u_int m6_rsvp_on; /* RSVP listening on this vif */
struct socket *m6_rsvpd; /* RSVP daemon socket */
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/netinet6/ip6_output.c
--- a/head/sys/netinet6/ip6_output.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/netinet6/ip6_output.c Wed Jul 25 16:47:10 2012 +0300
@@ -61,7 +61,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet6/ip6_output.c 232127 2012-02-24 20:06:04Z bz $");
+__FBSDID("$FreeBSD: head/sys/netinet6/ip6_output.c 238092 2012-07-04 07:37:53Z glebius $");
#include "opt_inet.h"
#include "opt_inet6.h"
@@ -83,6 +83,8 @@
#include <sys/syslog.h>
#include <sys/ucred.h>
+#include <machine/in_cksum.h>
+
#include <net/if.h>
#include <net/netisr.h>
#include <net/route.h>
@@ -182,12 +184,38 @@
}\
} while (/*CONSTCOND*/ 0)
+static void
+in6_delayed_cksum(struct mbuf *m, uint32_t plen, u_short offset)
+{
+ u_short csum;
+
+ csum = in_cksum_skip(m, offset + plen, offset);
+ if (m->m_pkthdr.csum_flags & CSUM_UDP_IPV6 && csum == 0)
+ csum = 0xffff;
+ offset += m->m_pkthdr.csum_data; /* checksum offset */
+
+ if (offset + sizeof(u_short) > m->m_len) {
+ printf("%s: delayed m_pullup, m->len: %d off: %d\n",
+ __func__, m->m_len, offset);
+ /*
+ * XXX this should not happen, but if it does, the correct
+ * behavior may be to insert the checksum in the appropriate
+ * next mbuf in the chain.
+ */
+ return;
+ }
+ *(u_short *)(m->m_data + offset) = csum;
+}
+
/*
* IP6 output. The packet in mbuf chain m contains a skeletal IP6
* header (with pri, len, nxt, hlim, src, dst).
* This function may modify ver and hlim only.
* The mbuf chain containing the packet will be freed.
* The mbuf opt, if present, will not be freed.
+ * If route_in6 ro is present and has ro_rt initialized, route lookup would be
+ * skipped and ro->ro_rt would be used. If ro is present but ro->ro_rt is NULL,
+ * then result of route lookup is stored in ro->ro_rt.
*
* type of "mtu": rt_rmx.rmx_mtu is u_long, ifnet.ifr_mtu is int, and
* nd_ifinfo.linkmtu is u_int32_t. so we use u_long to hold largest one,
@@ -218,12 +246,9 @@
struct in6_addr finaldst, src0, dst0;
u_int32_t zone;
struct route_in6 *ro_pmtu = NULL;
- int flevalid = 0;
int hdrsplit = 0;
int needipsec = 0;
-#ifdef SCTP
- int sw_csum;
-#endif
+ int sw_csum, tso;
#ifdef IPSEC
struct ipsec_output_state state;
struct ip6_rthdr *rh = NULL;
@@ -483,22 +508,20 @@
ro = &opt->ip6po_route;
dst = (struct sockaddr_in6 *)&ro->ro_dst;
#ifdef FLOWTABLE
- if (ro == &ip6route) {
+ if (ro->ro_rt == NULL) {
struct flentry *fle;
-
+
/*
* The flow table returns route entries valid for up to 30
* seconds; we rely on the remainder of ip_output() taking no
* longer than that long for the stability of ro_rt. The
* flow ID assignment must have happened before this point.
*/
- if ((fle = flowtable_lookup_mbuf(V_ip6_ft, m, AF_INET6)) != NULL) {
+ fle = flowtable_lookup_mbuf(V_ip6_ft, m, AF_INET6);
+ if (fle != NULL)
flow_to_route_in6(fle, ro);
- if (ro->ro_rt != NULL && ro->ro_lle != NULL)
- flevalid = 1;
- }
}
-#endif
+#endif
again:
/*
* if specified, try to fill in the traffic class field.
@@ -604,7 +627,7 @@
dst_sa.sin6_family = AF_INET6;
dst_sa.sin6_len = sizeof(dst_sa);
dst_sa.sin6_addr = ip6->ip6_dst;
- if (flevalid) {
+ if (ro->ro_rt) {
rt = ro->ro_rt;
ifp = ro->ro_rt->rt_ifp;
} else if ((error = in6_selectroute_fib(&dst_sa, opt, im6o, ro,
@@ -644,7 +667,7 @@
/*
* The outgoing interface must be in the zone of source and
- * destination addresses.
+ * destination addresses.
*/
origifp = ifp;
@@ -670,7 +693,7 @@
goto badscope;
}
- /* We should use ia_ifp to support the case of
+ /* We should use ia_ifp to support the case of
* sending packets to an address of our own.
*/
if (ia != NULL && ia->ia_ifp)
@@ -862,15 +885,13 @@
m->m_flags |= M_FASTFWD_OURS;
if (m->m_pkthdr.rcvif == NULL)
m->m_pkthdr.rcvif = V_loif;
- if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
+ if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA_IPV6) {
m->m_pkthdr.csum_flags |=
- CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
+ CSUM_DATA_VALID_IPV6 | CSUM_PSEUDO_HDR;
m->m_pkthdr.csum_data = 0xffff;
}
- m->m_pkthdr.csum_flags |=
- CSUM_IP_CHECKED | CSUM_IP_VALID;
#ifdef SCTP
- if (m->m_pkthdr.csum_flags & CSUM_SCTP)
+ if (m->m_pkthdr.csum_flags & CSUM_SCTP_IPV6)
m->m_pkthdr.csum_flags |= CSUM_SCTP_VALID;
#endif
error = netisr_queue(NETISR_IPV6, m);
@@ -884,15 +905,15 @@
if (m->m_flags & M_FASTFWD_OURS) {
if (m->m_pkthdr.rcvif == NULL)
m->m_pkthdr.rcvif = V_loif;
- if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
+ if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA_IPV6) {
m->m_pkthdr.csum_flags |=
- CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
+ CSUM_DATA_VALID_IPV6 | CSUM_PSEUDO_HDR;
m->m_pkthdr.csum_data = 0xffff;
}
#ifdef SCTP
- if (m->m_pkthdr.csum_flags & CSUM_SCTP)
- m->m_pkthdr.csum_flags |= CSUM_SCTP_VALID;
-#endif
+ if (m->m_pkthdr.csum_flags & CSUM_SCTP_IPV6)
+ m->m_pkthdr.csum_flags |= CSUM_SCTP_VALID;
+#endif
error = netisr_queue(NETISR_IPV6, m);
goto done;
}
@@ -927,16 +948,32 @@
* 4: if dontfrag == 1 && alwaysfrag == 1
* error, as we cannot handle this conflicting request
*/
+ sw_csum = m->m_pkthdr.csum_flags;
+ if (!hdrsplit) {
+ tso = ((sw_csum & ifp->if_hwassist & CSUM_TSO) != 0) ? 1 : 0;
+ sw_csum &= ~ifp->if_hwassist;
+ } else
+ tso = 0;
+ /*
+ * If we added extension headers, we will not do TSO and calculate the
+ * checksums ourselves for now.
+ * XXX-BZ Need a framework to know when the NIC can handle it, even
+ * with ext. hdrs.
+ */
+ if (sw_csum & CSUM_DELAY_DATA_IPV6) {
+ sw_csum &= ~CSUM_DELAY_DATA_IPV6;
+ in6_delayed_cksum(m, plen, sizeof(struct ip6_hdr));
+ }
#ifdef SCTP
- sw_csum = m->m_pkthdr.csum_flags & ~ifp->if_hwassist;
- if (sw_csum & CSUM_SCTP) {
+ if (sw_csum & CSUM_SCTP_IPV6) {
+ sw_csum &= ~CSUM_SCTP_IPV6;
sctp_delayed_cksum(m, sizeof(struct ip6_hdr));
- sw_csum &= ~CSUM_SCTP;
}
#endif
+ m->m_pkthdr.csum_flags &= ifp->if_hwassist;
tlen = m->m_pkthdr.len;
- if (opt && (opt->ip6po_flags & IP6PO_DONTFRAG))
+ if ((opt && (opt->ip6po_flags & IP6PO_DONTFRAG)) || tso)
dontfrag = 1;
else
dontfrag = 0;
@@ -945,7 +982,7 @@
error = EMSGSIZE;
goto bad;
}
- if (dontfrag && tlen > IN6_LINKMTU(ifp)) { /* case 2-b */
+ if (dontfrag && tlen > IN6_LINKMTU(ifp) && !tso) { /* case 2-b */
/*
* Even if the DONTFRAG option is specified, we cannot send the
* packet when the data length is larger than the MTU of the
@@ -1033,6 +1070,22 @@
goto bad;
}
+
+ /*
+ * If the interface will not calculate checksums on
+ * fragmented packets, then do it here.
+ * XXX-BZ handle the hw offloading case. Need flags.
+ */
+ if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA_IPV6) {
+ in6_delayed_cksum(m, plen, hlen);
+ m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA_IPV6;
+ }
+#ifdef SCTP
+ if (m->m_pkthdr.csum_flags & CSUM_SCTP_IPV6) {
+ sctp_delayed_cksum(m, hlen);
+ m->m_pkthdr.csum_flags &= ~CSUM_SCTP_IPV6;
+ }
+#endif
mnext = &m->m_nextpkt;
/*
@@ -1129,13 +1182,10 @@
V_ip6stat.ip6s_fragmented++;
done:
- if (ro == &ip6route && ro->ro_rt && flevalid == 0) {
- /* brace necessary for RTFREE */
- RTFREE(ro->ro_rt);
- } else if (ro_pmtu == &ip6route && ro_pmtu->ro_rt &&
- ((flevalid == 0) || (ro_pmtu != ro))) {
- RTFREE(ro_pmtu->ro_rt);
- }
+ if (ro == &ip6route)
+ RO_RTFREE(ro);
+ if (ro_pmtu == &ip6route)
+ RO_RTFREE(ro_pmtu);
#ifdef IPSEC
if (sp != NULL)
KEY_FREESP(&sp);
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/netinet6/ip6_var.h
--- a/head/sys/netinet6/ip6_var.h Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/netinet6/ip6_var.h Wed Jul 25 16:47:10 2012 +0300
@@ -58,7 +58,7 @@
* SUCH DAMAGE.
*
* @(#)ip_var.h 8.1 (Berkeley) 6/10/93
- * $FreeBSD: head/sys/netinet6/ip6_var.h 232127 2012-02-24 20:06:04Z bz $
+ * $FreeBSD: head/sys/netinet6/ip6_var.h 235956 2012-05-25 01:48:15Z bz $
*/
#ifndef _NETINET6_IP6_VAR_H_
@@ -388,9 +388,9 @@
int ip6_nexthdr __P((struct mbuf *, int, int, int *));
int ip6_lasthdr __P((struct mbuf *, int, int, int *));
-struct ip6aux *ip6_addaux __P((struct mbuf *));
+#ifdef __notyet__
struct ip6aux *ip6_findaux __P((struct mbuf *));
-void ip6_delaux __P((struct mbuf *));
+#endif
extern int (*ip6_mforward)(struct ip6_hdr *, struct ifnet *,
struct mbuf *);
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/netinet6/mld6.c
--- a/head/sys/netinet6/mld6.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/netinet6/mld6.c Wed Jul 25 16:47:10 2012 +0300
@@ -64,7 +64,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet6/mld6.c 229621 2012-01-05 19:00:36Z jhb $");
+__FBSDID("$FreeBSD: head/sys/netinet6/mld6.c 237736 2012-06-28 23:48:40Z bms $");
#include "opt_inet.h"
#include "opt_inet6.h"
@@ -833,7 +833,7 @@
mld = (struct mldv2_query *)(mtod(m, uint8_t *) + off);
maxdelay = ntohs(mld->mld_maxdelay); /* in 1/10ths of a second */
- if (maxdelay >= 32678) {
+ if (maxdelay >= 32768) {
maxdelay = (MLD_MRC_MANT(maxdelay) | 0x1000) <<
(MLD_MRC_EXP(maxdelay) + 3);
}
@@ -867,16 +867,10 @@
*/
if (IN6_IS_ADDR_UNSPECIFIED(&mld->mld_addr)) {
/*
- * General Queries SHOULD be directed to ff02::1.
* A general query with a source list has undefined
* behaviour; discard it.
*/
- struct in6_addr dst;
-
- dst = ip6->ip6_dst;
- in6_clearscope(&dst);
- if (!IN6_ARE_ADDR_EQUAL(&dst, &in6addr_linklocal_allnodes) ||
- nsrc > 0)
+ if (nsrc > 0)
return (EINVAL);
is_general_query = 1;
} else {
@@ -2203,6 +2197,7 @@
#endif
mld_v1_transmit_report(inm, MLD_LISTENER_DONE);
inm->in6m_state = MLD_NOT_MEMBER;
+ V_current_state_timers_running6 = 1;
} else if (mli->mli_version == MLD_VERSION_2) {
/*
* Stop group timer and all pending reports.
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/netinet6/nd6.c
--- a/head/sys/netinet6/nd6.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/netinet6/nd6.c Wed Jul 25 16:47:10 2012 +0300
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet6/nd6.c 232514 2012-03-04 18:51:45Z bz $");
+__FBSDID("$FreeBSD: head/sys/netinet6/nd6.c 235986 2012-05-25 09:27:16Z bz $");
#include "opt_inet.h"
#include "opt_inet6.h"
@@ -174,9 +174,7 @@
{
struct nd_ifinfo *nd;
- nd = (struct nd_ifinfo *)malloc(sizeof(*nd), M_IP6NDP, M_WAITOK);
- bzero(nd, sizeof(*nd));
-
+ nd = (struct nd_ifinfo *)malloc(sizeof(*nd), M_IP6NDP, M_WAITOK|M_ZERO);
nd->initialized = 1;
nd->chlim = IPV6_DEFHLIM;
@@ -284,10 +282,9 @@
struct nd_opt_hdr *nd_opt;
int olen;
- if (ndopts == NULL)
- panic("ndopts == NULL in nd6_option");
- if (ndopts->nd_opts_last == NULL)
- panic("uninitialized ndopts in nd6_option");
+ KASSERT(ndopts != NULL, ("%s: ndopts == NULL", __func__));
+ KASSERT(ndopts->nd_opts_last != NULL, ("%s: uninitialized ndopts",
+ __func__));
if (ndopts->nd_opts_search == NULL)
return NULL;
if (ndopts->nd_opts_done)
@@ -335,10 +332,9 @@
struct nd_opt_hdr *nd_opt;
int i = 0;
- if (ndopts == NULL)
- panic("ndopts == NULL in nd6_options");
- if (ndopts->nd_opts_last == NULL)
- panic("uninitialized ndopts in nd6_options");
+ KASSERT(ndopts != NULL, ("%s: ndopts == NULL", __func__));
+ KASSERT(ndopts->nd_opts_last != NULL, ("%s: uninitialized ndopts",
+ __func__));
if (ndopts->nd_opts_search == NULL)
return 0;
@@ -1174,11 +1170,13 @@
void
nd6_rtrequest(int req, struct rtentry *rt, struct rt_addrinfo *info)
{
- struct sockaddr_in6 *gateway = (struct sockaddr_in6 *)rt->rt_gateway;
+ struct sockaddr_in6 *gateway;
struct nd_defrouter *dr;
- struct ifnet *ifp = rt->rt_ifp;
+ struct ifnet *ifp;
RT_LOCK_ASSERT(rt);
+ gateway = (struct sockaddr_in6 *)rt->rt_gateway;
+ ifp = rt->rt_ifp;
switch (req) {
case RTM_ADD:
@@ -1547,10 +1545,8 @@
IF_AFDATA_UNLOCK_ASSERT(ifp);
- if (ifp == NULL)
- panic("ifp == NULL in nd6_cache_lladdr");
- if (from == NULL)
- panic("from == NULL in nd6_cache_lladdr");
+ KASSERT(ifp != NULL, ("%s: ifp == NULL", __func__));
+ KASSERT(from != NULL, ("%s: from == NULL", __func__));
/* nothing must be updated for unspecified address */
if (IN6_IS_ADDR_UNSPECIFIED(from))
@@ -2074,6 +2070,8 @@
}
return (error);
}
+ /* Reset layer specific mbuf flags to avoid confusing lower layers. */
+ m->m_flags &= ~(M_PROTOFLAGS);
if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
return ((*ifp->if_output)(origifp, m, (struct sockaddr *)dst,
NULL));
@@ -2239,7 +2237,6 @@
for (m_hold = ln->la_hold; m_hold; m_hold = m_hold_next) {
m_hold_next = m_hold->m_nextpkt;
- m_hold->m_nextpkt = NULL;
m_freem(m_hold);
}
@@ -2262,128 +2259,101 @@
static int
nd6_sysctl_drlist(SYSCTL_HANDLER_ARGS)
{
+ struct in6_defrouter d;
+ struct nd_defrouter *dr;
int error;
- char buf[1024] __aligned(4);
- struct in6_defrouter *d, *de;
- struct nd_defrouter *dr;
if (req->newptr)
- return EPERM;
- error = 0;
+ return (EPERM);
+ bzero(&d, sizeof(d));
+ d.rtaddr.sin6_family = AF_INET6;
+ d.rtaddr.sin6_len = sizeof(d.rtaddr);
+
+ /*
+ * XXX locking
+ */
TAILQ_FOREACH(dr, &V_nd_defrouter, dr_entry) {
- d = (struct in6_defrouter *)buf;
- de = (struct in6_defrouter *)(buf + sizeof(buf));
-
- if (d + 1 <= de) {
- bzero(d, sizeof(*d));
- d->rtaddr.sin6_family = AF_INET6;
- d->rtaddr.sin6_len = sizeof(d->rtaddr);
- d->rtaddr.sin6_addr = dr->rtaddr;
- error = sa6_recoverscope(&d->rtaddr);
- if (error != 0)
- return (error);
- d->flags = dr->flags;
- d->rtlifetime = dr->rtlifetime;
- d->expire = dr->expire;
- d->if_index = dr->ifp->if_index;
- } else
- panic("buffer too short");
-
- error = SYSCTL_OUT(req, buf, sizeof(*d));
- if (error)
- break;
+ d.rtaddr.sin6_addr = dr->rtaddr;
+ error = sa6_recoverscope(&d.rtaddr);
+ if (error != 0)
+ return (error);
+ d.flags = dr->flags;
+ d.rtlifetime = dr->rtlifetime;
+ d.expire = dr->expire;
+ d.if_index = dr->ifp->if_index;
+ error = SYSCTL_OUT(req, &d, sizeof(d));
+ if (error != 0)
+ return (error);
}
-
- return (error);
+ return (0);
}
static int
nd6_sysctl_prlist(SYSCTL_HANDLER_ARGS)
{
+ struct in6_prefix p;
+ struct sockaddr_in6 s6;
+ struct nd_prefix *pr;
+ struct nd_pfxrouter *pfr;
+ time_t maxexpire;
int error;
- char buf[1024] __aligned(4);
- struct in6_prefix *p, *pe;
- struct nd_prefix *pr;
char ip6buf[INET6_ADDRSTRLEN];
if (req->newptr)
- return EPERM;
- error = 0;
+ return (EPERM);
+ bzero(&p, sizeof(p));
+ p.origin = PR_ORIG_RA;
+ bzero(&s6, sizeof(s6));
+ s6.sin6_family = AF_INET6;
+ s6.sin6_len = sizeof(s6);
+
+ /*
+ * XXX locking
+ */
LIST_FOREACH(pr, &V_nd_prefix, ndpr_entry) {
- u_short advrtrs;
- size_t advance;
- struct sockaddr_in6 *sin6, *s6;
- struct nd_pfxrouter *pfr;
-
- p = (struct in6_prefix *)buf;
- pe = (struct in6_prefix *)(buf + sizeof(buf));
-
- if (p + 1 <= pe) {
- bzero(p, sizeof(*p));
- sin6 = (struct sockaddr_in6 *)(p + 1);
-
- p->prefix = pr->ndpr_prefix;
- if (sa6_recoverscope(&p->prefix)) {
+ p.prefix = pr->ndpr_prefix;
+ if (sa6_recoverscope(&p.prefix)) {
+ log(LOG_ERR, "scope error in prefix list (%s)\n",
+ ip6_sprintf(ip6buf, &p.prefix.sin6_addr));
+ /* XXX: press on... */
+ }
+ p.raflags = pr->ndpr_raf;
+ p.prefixlen = pr->ndpr_plen;
+ p.vltime = pr->ndpr_vltime;
+ p.pltime = pr->ndpr_pltime;
+ p.if_index = pr->ndpr_ifp->if_index;
+ if (pr->ndpr_vltime == ND6_INFINITE_LIFETIME)
+ p.expire = 0;
+ else {
+ /* XXX: we assume time_t is signed. */
+ maxexpire = (-1) &
+ ~((time_t)1 << ((sizeof(maxexpire) * 8) - 1));
+ if (pr->ndpr_vltime < maxexpire - pr->ndpr_lastupdate)
+ p.expire = pr->ndpr_lastupdate +
+ pr->ndpr_vltime;
+ else
+ p.expire = maxexpire;
+ }
+ p.refcnt = pr->ndpr_refcnt;
+ p.flags = pr->ndpr_stateflags;
+ p.advrtrs = 0;
+ LIST_FOREACH(pfr, &pr->ndpr_advrtrs, pfr_entry)
+ p.advrtrs++;
+ error = SYSCTL_OUT(req, &p, sizeof(p));
+ if (error != 0)
+ return (error);
+ LIST_FOREACH(pfr, &pr->ndpr_advrtrs, pfr_entry) {
+ s6.sin6_addr = pfr->router->rtaddr;
+ if (sa6_recoverscope(&s6))
log(LOG_ERR,
"scope error in prefix list (%s)\n",
- ip6_sprintf(ip6buf, &p->prefix.sin6_addr));
- /* XXX: press on... */
- }
- p->raflags = pr->ndpr_raf;
- p->prefixlen = pr->ndpr_plen;
- p->vltime = pr->ndpr_vltime;
- p->pltime = pr->ndpr_pltime;
- p->if_index = pr->ndpr_ifp->if_index;
- if (pr->ndpr_vltime == ND6_INFINITE_LIFETIME)
- p->expire = 0;
- else {
- time_t maxexpire;
-
- /* XXX: we assume time_t is signed. */
- maxexpire = (-1) &
- ~((time_t)1 <<
- ((sizeof(maxexpire) * 8) - 1));
- if (pr->ndpr_vltime <
- maxexpire - pr->ndpr_lastupdate) {
- p->expire = pr->ndpr_lastupdate +
- pr->ndpr_vltime;
- } else
- p->expire = maxexpire;
- }
- p->refcnt = pr->ndpr_refcnt;
- p->flags = pr->ndpr_stateflags;
- p->origin = PR_ORIG_RA;
- advrtrs = 0;
- LIST_FOREACH(pfr, &pr->ndpr_advrtrs, pfr_entry) {
- if ((void *)&sin6[advrtrs + 1] > (void *)pe) {
- advrtrs++;
- continue;
- }
- s6 = &sin6[advrtrs];
- bzero(s6, sizeof(*s6));
- s6->sin6_family = AF_INET6;
- s6->sin6_len = sizeof(*sin6);
- s6->sin6_addr = pfr->router->rtaddr;
- if (sa6_recoverscope(s6)) {
- log(LOG_ERR,
- "scope error in "
- "prefix list (%s)\n",
- ip6_sprintf(ip6buf,
- &pfr->router->rtaddr));
- }
- advrtrs++;
- }
- p->advrtrs = advrtrs;
- } else
- panic("buffer too short");
-
- advance = sizeof(*p) + sizeof(*sin6) * advrtrs;
- error = SYSCTL_OUT(req, buf, advance);
- if (error)
- break;
+ ip6_sprintf(ip6buf, &pfr->router->rtaddr));
+ error = SYSCTL_OUT(req, &s6, sizeof(s6));
+ if (error != 0)
+ return (error);
+ }
}
-
- return (error);
+ return (0);
}
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/netinet6/nd6.h
--- a/head/sys/netinet6/nd6.h Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/netinet6/nd6.h Wed Jul 25 16:47:10 2012 +0300
@@ -27,7 +27,7 @@
* SUCH DAMAGE.
*
* $KAME: nd6.h,v 1.76 2001/12/18 02:10:31 itojun Exp $
- * $FreeBSD: head/sys/netinet6/nd6.h 229547 2012-01-05 01:14:35Z bz $
+ * $FreeBSD: head/sys/netinet6/nd6.h 238273 2012-07-09 06:21:46Z hrs $
*/
#ifndef _NETINET6_ND6_H_
@@ -79,7 +79,7 @@
#define ND6_IFF_PERFORMNUD 0x1
#define ND6_IFF_ACCEPT_RTADV 0x2
-#define ND6_IFF_PREFER_SOURCE 0x4 /* XXX: not related to ND. */
+#define ND6_IFF_PREFER_SOURCE 0x4 /* Not used in FreeBSD. */
#define ND6_IFF_IFDISABLED 0x8 /* IPv6 operation is disabled due to
* DAD failure. (XXX: not ND-specific)
*/
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/netinet6/nd6_nbr.c
--- a/head/sys/netinet6/nd6_nbr.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/netinet6/nd6_nbr.c Wed Jul 25 16:47:10 2012 +0300
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet6/nd6_nbr.c 231852 2012-02-17 02:39:58Z bz $");
+__FBSDID("$FreeBSD: head/sys/netinet6/nd6_nbr.c 238092 2012-07-04 07:37:53Z glebius $");
#include "opt_inet.h"
#include "opt_inet6.h"
@@ -595,9 +595,9 @@
icmp6_ifstat_inc(ifp, ifs6_out_neighborsolicit);
ICMP6STAT_INC(icp6s_outhist[ND_NEIGHBOR_SOLICIT]);
- if (ro.ro_rt) { /* we don't cache this route. */
- RTFREE(ro.ro_rt);
- }
+ /* We don't cache this route. */
+ RO_RTFREE(&ro);
+
return;
bad:
@@ -1124,9 +1124,9 @@
icmp6_ifstat_inc(ifp, ifs6_out_neighboradvert);
ICMP6STAT_INC(icp6s_outhist[ND_NEIGHBOR_ADVERT]);
- if (ro.ro_rt) { /* we don't cache this route. */
- RTFREE(ro.ro_rt);
- }
+ /* We don't cache this route. */
+ RO_RTFREE(&ro);
+
return;
bad:
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/netinet6/route6.c
--- a/head/sys/netinet6/route6.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/netinet6/route6.c Wed Jul 25 16:47:10 2012 +0300
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/netinet6/route6.c 235954 2012-05-25 01:43:52Z bz $");
#include "opt_inet.h"
#include "opt_inet6.h"
@@ -62,6 +62,7 @@
struct mbuf *m = *mp;
struct ip6_rthdr *rh;
int off = *offp, rhlen;
+#ifdef __notyet__
struct ip6aux *ip6a;
ip6a = ip6_findaux(m);
@@ -73,6 +74,7 @@
return IPPROTO_DONE;
}
}
+#endif
#ifndef PULLDOWN_TEST
IP6_EXTHDR_CHECK(m, off, sizeof(*rh), IPPROTO_DONE);
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/netinet6/scope6.c
--- a/head/sys/netinet6/scope6.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/netinet6/scope6.c Wed Jul 25 16:47:10 2012 +0300
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/netinet6/scope6.c 235916 2012-05-24 16:30:13Z bz $");
#include <sys/param.h>
#include <sys/malloc.h>
@@ -494,3 +494,16 @@
return (modified);
}
+
+/*
+ * Return the scope identifier or zero.
+ */
+uint16_t
+in6_getscope(struct in6_addr *in6)
+{
+
+ if (IN6_IS_SCOPE_LINKLOCAL(in6) || IN6_IS_ADDR_MC_INTFACELOCAL(in6))
+ return (in6->s6_addr16[1]);
+
+ return (0);
+}
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/netinet6/scope6_var.h
--- a/head/sys/netinet6/scope6_var.h Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/netinet6/scope6_var.h Wed Jul 25 16:47:10 2012 +0300
@@ -27,7 +27,7 @@
* SUCH DAMAGE.
*
* $KAME: scope6_var.h,v 1.4 2000/05/18 15:03:27 jinmei Exp $
- * $FreeBSD: head/sys/netinet6/scope6_var.h 229127 2011-12-31 16:19:22Z bz $
+ * $FreeBSD: head/sys/netinet6/scope6_var.h 235916 2012-05-24 16:30:13Z bz $
*/
#ifndef _NETINET6_SCOPE6_VAR_H_
@@ -54,6 +54,7 @@
int sa6_recoverscope __P((struct sockaddr_in6 *));
int in6_setscope __P((struct in6_addr *, struct ifnet *, u_int32_t *));
int in6_clearscope __P((struct in6_addr *));
+uint16_t in6_getscope(struct in6_addr *);
#endif /* _KERNEL */
#endif /* _NETINET6_SCOPE6_VAR_H_ */
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/netinet6/sctp6_usrreq.c
--- a/head/sys/netinet6/sctp6_usrreq.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/netinet6/sctp6_usrreq.c Wed Jul 25 16:47:10 2012 +0300
@@ -1,7 +1,7 @@
/*-
* Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
- * Copyright (c) 2008-2011, by Randall Stewart. All rights reserved.
- * Copyright (c) 2008-2011, by Michael Tuexen. All rights reserved.
+ * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
+ * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -29,17 +29,17 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-/* $KAME: sctp6_usrreq.c,v 1.38 2005/08/24 08:08:56 suz Exp $ */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet6/sctp6_usrreq.c 233005 2012-03-15 14:22:05Z tuexen $");
+__FBSDID("$FreeBSD: head/sys/netinet6/sctp6_usrreq.c 238501 2012-07-15 20:16:17Z tuexen $");
#include <netinet/sctp_os.h>
+#ifdef INET6
#include <sys/proc.h>
#include <netinet/sctp_pcb.h>
#include <netinet/sctp_header.h>
#include <netinet/sctp_var.h>
-#if defined(INET6)
+#ifdef INET6
#include <netinet6/sctp6_var.h>
#endif
#include <netinet/sctp_sysctl.h>
@@ -58,7 +58,7 @@
#ifdef IPSEC
#include <netipsec/ipsec.h>
-#if defined(INET6)
+#ifdef INET6
#include <netipsec/ipsec6.h>
#endif /* INET6 */
#endif /* IPSEC */
@@ -69,232 +69,128 @@
sctp6_input(struct mbuf **i_pak, int *offp, int proto)
{
struct mbuf *m;
+ int iphlen;
+ uint32_t vrf_id;
+ uint8_t ecn_bits;
+ struct sockaddr_in6 src, dst;
struct ip6_hdr *ip6;
struct sctphdr *sh;
- struct sctp_inpcb *in6p = NULL;
- struct sctp_nets *net;
- int refcount_up = 0;
- uint32_t vrf_id = 0;
+ struct sctp_chunkhdr *ch;
+ int length, offset;
-#ifdef IPSEC
- struct inpcb *in6p_ip;
+#if !defined(SCTP_WITH_NO_CSUM)
+ uint8_t compute_crc;
#endif
- struct sctp_chunkhdr *ch;
- int length, offset, iphlen;
- uint8_t ecn_bits;
- struct sctp_tcb *stcb = NULL;
- int pkt_len = 0;
-
-#if !defined(SCTP_WITH_NO_CSUM)
- uint32_t check, calc_check;
-
-#endif
- int off = *offp;
+ uint32_t mflowid;
+ uint8_t use_mflowid;
uint16_t port = 0;
- /* get the VRF and table id's */
+ iphlen = *offp;
if (SCTP_GET_PKT_VRFID(*i_pak, vrf_id)) {
SCTP_RELEASE_PKT(*i_pak);
- return (-1);
+ return (IPPROTO_DONE);
}
m = SCTP_HEADER_TO_CHAIN(*i_pak);
- pkt_len = SCTP_HEADER_LEN((*i_pak));
+#ifdef SCTP_MBUF_LOGGING
+ /* Log in any input mbufs */
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
+ struct mbuf *mat;
-#ifdef SCTP_PACKET_LOGGING
- sctp_packet_log(m, pkt_len);
+ for (mat = m; mat; mat = SCTP_BUF_NEXT(mat)) {
+ if (SCTP_BUF_IS_EXTENDED(mat)) {
+ sctp_log_mb(mat, SCTP_MBUF_INPUT);
+ }
+ }
+ }
#endif
+#ifdef SCTP_PACKET_LOGGING
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING) {
+ sctp_packet_log(m);
+ }
+#endif
+ SCTPDBG(SCTP_DEBUG_CRCOFFLOAD,
+ "sctp6_input(): Packet of length %d received on %s with csum_flags 0x%x.\n",
+ m->m_pkthdr.len,
+ if_name(m->m_pkthdr.rcvif),
+ m->m_pkthdr.csum_flags);
+ if (m->m_flags & M_FLOWID) {
+ mflowid = m->m_pkthdr.flowid;
+ use_mflowid = 1;
+ } else {
+ mflowid = 0;
+ use_mflowid = 0;
+ }
+ SCTP_STAT_INCR(sctps_recvpackets);
+ SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
+ /* Get IP, SCTP, and first chunk header together in the first mbuf. */
+ offset = iphlen + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr);
ip6 = mtod(m, struct ip6_hdr *);
- /* Ensure that (sctphdr + sctp_chunkhdr) in a row. */
- IP6_EXTHDR_GET(sh, struct sctphdr *, m, off,
- (int)(sizeof(*sh) + sizeof(*ch)));
+ IP6_EXTHDR_GET(sh, struct sctphdr *, m, iphlen,
+ (int)(sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr)));
if (sh == NULL) {
SCTP_STAT_INCR(sctps_hdrops);
return (IPPROTO_DONE);
}
ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr));
- iphlen = off;
- offset = iphlen + sizeof(*sh) + sizeof(*ch);
- SCTPDBG(SCTP_DEBUG_INPUT1,
- "sctp6_input() length:%d iphlen:%d\n", pkt_len, iphlen);
-
-
-#if defined(NFAITH) && NFAITH > 0
-
- if (faithprefix_p != NULL && (*faithprefix_p) (&ip6->ip6_dst)) {
+ offset -= sizeof(struct sctp_chunkhdr);
+ memset(&src, 0, sizeof(struct sockaddr_in6));
+ src.sin6_family = AF_INET6;
+ src.sin6_len = sizeof(struct sockaddr_in6);
+ src.sin6_port = sh->src_port;
+ src.sin6_addr = ip6->ip6_src;
+ if (in6_setscope(&src.sin6_addr, m->m_pkthdr.rcvif, NULL) != 0) {
+ goto out;
+ }
+ memset(&dst, 0, sizeof(struct sockaddr_in6));
+ dst.sin6_family = AF_INET6;
+ dst.sin6_len = sizeof(struct sockaddr_in6);
+ dst.sin6_port = sh->dest_port;
+ dst.sin6_addr = ip6->ip6_dst;
+ if (in6_setscope(&dst.sin6_addr, m->m_pkthdr.rcvif, NULL) != 0) {
+ goto out;
+ }
+ if (faithprefix_p != NULL && (*faithprefix_p) (&dst.sin6_addr)) {
/* XXX send icmp6 host/port unreach? */
- goto bad;
+ goto out;
}
-#endif /* NFAITH defined and > 0 */
- SCTP_STAT_INCR(sctps_recvpackets);
- SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
- SCTPDBG(SCTP_DEBUG_INPUT1, "V6 input gets a packet iphlen:%d pktlen:%d\n",
- iphlen, pkt_len);
+ length = ntohs(ip6->ip6_plen) + iphlen;
+ /* Validate mbuf chain length with IP payload length. */
+ if (SCTP_HEADER_LEN(m) != length) {
+ SCTPDBG(SCTP_DEBUG_INPUT1,
+ "sctp6_input() length:%d reported length:%d\n", length, SCTP_HEADER_LEN(m));
+ SCTP_STAT_INCR(sctps_hdrops);
+ goto out;
+ }
if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
- /* No multi-cast support in SCTP */
- goto bad;
+ goto out;
}
- /* destination port of 0 is illegal, based on RFC2960. */
- if (sh->dest_port == 0)
- goto bad;
-
- SCTPDBG(SCTP_DEBUG_CRCOFFLOAD,
- "sctp_input(): Packet of length %d received on %s with csum_flags 0x%x.\n",
- m->m_pkthdr.len,
- if_name(m->m_pkthdr.rcvif),
- m->m_pkthdr.csum_flags);
+ ecn_bits = ((ntohl(ip6->ip6_flow) >> 20) & 0x000000ff);
#if defined(SCTP_WITH_NO_CSUM)
SCTP_STAT_INCR(sctps_recvnocrc);
#else
if (m->m_pkthdr.csum_flags & CSUM_SCTP_VALID) {
SCTP_STAT_INCR(sctps_recvhwcrc);
- goto sctp_skip_csum;
+ compute_crc = 0;
+ } else {
+ SCTP_STAT_INCR(sctps_recvswcrc);
+ compute_crc = 1;
}
- check = sh->checksum; /* save incoming checksum */
- if ((check == 0) && (SCTP_BASE_SYSCTL(sctp_no_csum_on_loopback)) &&
- (IN6_ARE_ADDR_EQUAL(&ip6->ip6_src, &ip6->ip6_dst))) {
- SCTP_STAT_INCR(sctps_recvnocrc);
- goto sctp_skip_csum;
+#endif
+ sctp_common_input_processing(&m, iphlen, offset, length,
+ (struct sockaddr *)&src,
+ (struct sockaddr *)&dst,
+ sh, ch,
+#if !defined(SCTP_WITH_NO_CSUM)
+ compute_crc,
+#endif
+ ecn_bits,
+ use_mflowid, mflowid,
+ vrf_id, port);
+out:
+ if (m) {
+ sctp_m_freem(m);
}
- sh->checksum = 0; /* prepare for calc */
- calc_check = sctp_calculate_cksum(m, iphlen);
- SCTP_STAT_INCR(sctps_recvswcrc);
- if (calc_check != check) {
- SCTPDBG(SCTP_DEBUG_INPUT1, "Bad CSUM on SCTP packet calc_check:%x check:%x m:%p phlen:%d\n",
- calc_check, check, m, iphlen);
- stcb = sctp_findassociation_addr(m, offset - sizeof(*ch),
- sh, ch, &in6p, &net, vrf_id);
- if ((net) && (port)) {
- if (net->port == 0) {
- sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr));
- }
- net->port = port;
- }
- if ((net != NULL) && (m->m_flags & M_FLOWID)) {
- net->flowid = m->m_pkthdr.flowid;
-#ifdef INVARIANTS
- net->flowidset = 1;
-#endif
- }
- /* in6p's ref-count increased && stcb locked */
- if ((in6p) && (stcb)) {
- sctp_send_packet_dropped(stcb, net, m, iphlen, 1);
- sctp_chunk_output((struct sctp_inpcb *)in6p, stcb, SCTP_OUTPUT_FROM_INPUT_ERROR, SCTP_SO_NOT_LOCKED);
- } else if ((in6p != NULL) && (stcb == NULL)) {
- refcount_up = 1;
- }
- SCTP_STAT_INCR(sctps_badsum);
- SCTP_STAT_INCR_COUNTER32(sctps_checksumerrors);
- goto bad;
- }
- sh->checksum = calc_check;
-
-sctp_skip_csum:
-#endif
- net = NULL;
- /*
- * Locate pcb and tcb for datagram sctp_findassociation_addr() wants
- * IP/SCTP/first chunk header...
- */
- stcb = sctp_findassociation_addr(m, offset - sizeof(*ch),
- sh, ch, &in6p, &net, vrf_id);
- if ((net) && (port)) {
- if (net->port == 0) {
- sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr));
- }
- net->port = port;
- }
- if ((net != NULL) && (m->m_flags & M_FLOWID)) {
- net->flowid = m->m_pkthdr.flowid;
-#ifdef INVARIANTS
- net->flowidset = 1;
-#endif
- }
- /* in6p's ref-count increased */
- if (in6p == NULL) {
- struct sctp_init_chunk *init_chk, chunk_buf;
-
- SCTP_STAT_INCR(sctps_noport);
- if (ch->chunk_type == SCTP_INITIATION) {
- /*
- * we do a trick here to get the INIT tag, dig in
- * and get the tag from the INIT and put it in the
- * common header.
- */
- init_chk = (struct sctp_init_chunk *)sctp_m_getptr(m,
- iphlen + sizeof(*sh), sizeof(*init_chk),
- (uint8_t *) & chunk_buf);
- if (init_chk)
- sh->v_tag = init_chk->init.initiate_tag;
- else
- sh->v_tag = 0;
- }
- if (ch->chunk_type == SCTP_SHUTDOWN_ACK) {
- sctp_send_shutdown_complete2(m, sh, vrf_id, port);
- goto bad;
- }
- if (ch->chunk_type == SCTP_SHUTDOWN_COMPLETE) {
- goto bad;
- }
- if (ch->chunk_type != SCTP_ABORT_ASSOCIATION) {
- if ((SCTP_BASE_SYSCTL(sctp_blackhole) == 0) ||
- ((SCTP_BASE_SYSCTL(sctp_blackhole) == 1) &&
- (ch->chunk_type != SCTP_INIT))) {
- sctp_send_abort(m, iphlen, sh, 0, NULL, vrf_id, port);
- }
- }
- goto bad;
- } else if (stcb == NULL) {
- refcount_up = 1;
- }
-#ifdef IPSEC
- /*
- * Check AH/ESP integrity.
- */
- in6p_ip = (struct inpcb *)in6p;
- if (in6p_ip && (ipsec6_in_reject(m, in6p_ip))) {
-/* XXX */
- MODULE_GLOBAL(ipsec6stat).in_polvio++;
- goto bad;
- }
-#endif /* IPSEC */
-
- /*
- * CONTROL chunk processing
- */
- offset -= sizeof(*ch);
- ecn_bits = ((ntohl(ip6->ip6_flow) >> 20) & 0x000000ff);
-
- /* Length now holds the total packet length payload + iphlen */
- length = ntohs(ip6->ip6_plen) + iphlen;
-
- /* sa_ignore NO_NULL_CHK */
- sctp_common_input_processing(&m, iphlen, offset, length, sh, ch,
- in6p, stcb, net, ecn_bits, vrf_id, port);
- /* inp's ref-count reduced && stcb unlocked */
- /* XXX this stuff below gets moved to appropriate parts later... */
- if (m)
- sctp_m_freem(m);
- if ((in6p) && refcount_up) {
- /* reduce ref-count */
- SCTP_INP_WLOCK(in6p);
- SCTP_INP_DECR_REF(in6p);
- SCTP_INP_WUNLOCK(in6p);
- }
- return (IPPROTO_DONE);
-
-bad:
- if (stcb) {
- SCTP_TCB_UNLOCK(stcb);
- }
- if ((in6p) && refcount_up) {
- /* reduce ref-count */
- SCTP_INP_WLOCK(in6p);
- SCTP_INP_DECR_REF(in6p);
- SCTP_INP_WUNLOCK(in6p);
- }
- if (m)
- sctp_m_freem(m);
return (IPPROTO_DONE);
}
@@ -384,14 +280,12 @@
struct sctp_tcb *stcb,
struct sctp_nets *net)
{
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
#endif
+
/* protection */
- int reason;
-
-
if ((inp == NULL) || (stcb == NULL) || (net == NULL) ||
(sh == NULL) || (to == NULL)) {
if (stcb)
@@ -428,8 +322,7 @@
net->dest_state &= ~SCTP_ADDR_REACHABLE;
net->dest_state &= ~SCTP_ADDR_PF;
sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN,
- stcb, SCTP_FAILED_THRESHOLD,
- (void *)net, SCTP_SO_NOT_LOCKED);
+ stcb, 0, (void *)net, SCTP_SO_NOT_LOCKED);
}
SCTP_TCB_UNLOCK(stcb);
} else if ((icmph->icmp6_code == ICMP_UNREACH_PROTOCOL) ||
@@ -441,9 +334,8 @@
* now is dead. In either case treat it like a OOTB abort
* with no TCB
*/
- reason = SCTP_PEER_FAULTY;
- sctp_abort_notification(stcb, reason, SCTP_SO_NOT_LOCKED);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+ sctp_abort_notification(stcb, 1, 0, NULL, SCTP_SO_NOT_LOCKED);
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
so = SCTP_INP_SO(inp);
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
@@ -452,7 +344,7 @@
atomic_subtract_int(&stcb->asoc.refcnt, 1);
#endif
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_2);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
/* SCTP_TCB_UNLOCK(stcb); MT: I think this is not needed. */
#endif
@@ -516,8 +408,8 @@
final.sin6_family = AF_INET6;
final.sin6_addr = ((struct sockaddr_in6 *)pktdst)->sin6_addr;
final.sin6_port = sh.dest_port;
- stcb = sctp_findassociation_addr_sa((struct sockaddr *)ip6cp->ip6c_src,
- (struct sockaddr *)&final,
+ stcb = sctp_findassociation_addr_sa((struct sockaddr *)&final,
+ (struct sockaddr *)ip6cp->ip6c_src,
&inp, &net, 1, vrf_id);
/* inp's ref-count increased && stcb locked */
if (stcb != NULL && inp && (inp->sctp_socket != NULL)) {
@@ -584,8 +476,8 @@
if (error)
return (error);
- stcb = sctp_findassociation_addr_sa(sin6tosa(&addrs[0]),
- sin6tosa(&addrs[1]),
+ stcb = sctp_findassociation_addr_sa(sin6tosa(&addrs[1]),
+ sin6tosa(&addrs[0]),
&inp, &net, 1, vrf_id);
if (stcb == NULL || inp == NULL || inp->sctp_socket == NULL) {
if ((inp != NULL) && (stcb == NULL)) {
@@ -1349,3 +1241,5 @@
.pru_sosend = sctp_sosend,
.pru_soreceive = sctp_soreceive
};
+
+#endif
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/netinet6/sctp6_var.h
--- a/head/sys/netinet6/sctp6_var.h Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/netinet6/sctp6_var.h Wed Jul 25 16:47:10 2012 +0300
@@ -1,7 +1,7 @@
/*-
* Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
- * Copyright (c) 2008-2011, by Randall Stewart. All rights reserved.
- * Copyright (c) 2008-2011, by Michael Tuexen. All rights reserved.
+ * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
+ * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -29,14 +29,13 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-/* $KAME: sctp6_var.h,v 1.7 2004/08/17 04:06:22 itojun Exp $ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: head/sys/netinet6/sctp6_var.h 235828 2012-05-23 11:26:28Z tuexen $");
#ifndef _NETINET6_SCTP6_VAR_H_
#define _NETINET6_SCTP6_VAR_H_
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet6/sctp6_var.h 230138 2012-01-15 14:03:05Z tuexen $");
-
#if defined(_KERNEL)
SYSCTL_DECL(_net_inet6_sctp6);
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/netinet6/udp6_usrreq.c
--- a/head/sys/netinet6/udp6_usrreq.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/netinet6/udp6_usrreq.c Wed Jul 25 16:47:10 2012 +0300
@@ -67,7 +67,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet6/udp6_usrreq.c 225044 2011-08-20 17:05:11Z bz $");
+__FBSDID("$FreeBSD: head/sys/netinet6/udp6_usrreq.c 236170 2012-05-28 09:30:13Z bz $");
#include "opt_inet.h"
#include "opt_inet6.h"
@@ -185,6 +185,7 @@
#ifdef IPFIREWALL_FORWARD
struct m_tag *fwd_tag;
#endif
+ uint16_t uh_sum;
ifp = m->m_pkthdr.rcvif;
ip6 = mtod(m, struct ip6_hdr *);
@@ -228,7 +229,18 @@
UDPSTAT_INC(udps_nosum);
goto badunlocked;
}
- if (in6_cksum(m, IPPROTO_UDP, off, ulen) != 0) {
+
+ if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID_IPV6) {
+ if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR)
+ uh_sum = m->m_pkthdr.csum_data;
+ else
+ uh_sum = in6_cksum_pseudo(ip6, ulen,
+ IPPROTO_UDP, m->m_pkthdr.csum_data);
+ uh_sum ^= 0xffff;
+ } else
+ uh_sum = in6_cksum(m, IPPROTO_UDP, off, ulen);
+
+ if (uh_sum != 0) {
UDPSTAT_INC(udps_badsum);
goto badunlocked;
}
@@ -771,10 +783,9 @@
ip6->ip6_src = *laddr;
ip6->ip6_dst = *faddr;
- if ((udp6->uh_sum = in6_cksum(m, IPPROTO_UDP,
- sizeof(struct ip6_hdr), plen)) == 0) {
- udp6->uh_sum = 0xffff;
- }
+ udp6->uh_sum = in6_cksum_pseudo(ip6, plen, IPPROTO_UDP, 0);
+ m->m_pkthdr.csum_flags = CSUM_UDP_IPV6;
+ m->m_pkthdr.csum_data = offsetof(struct udphdr, uh_sum);
flags = 0;
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/netipsec/ipsec_output.c
--- a/head/sys/netipsec/ipsec_output.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/netipsec/ipsec_output.c Wed Jul 25 16:47:10 2012 +0300
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: head/sys/netipsec/ipsec_output.c 231852 2012-02-17 02:39:58Z bz $
+ * $FreeBSD: head/sys/netipsec/ipsec_output.c 238700 2012-07-22 17:46:05Z bz $
*/
/*
@@ -165,8 +165,7 @@
*/
if (isr->next) {
V_ipsec4stat.ips_out_bundlesa++;
- sav = isr->next->sav;
- saidx = &sav->sah->saidx;
+ /* XXX-BZ currently only support same AF bundles. */
switch (saidx->dst.sa.sa_family) {
#ifdef INET
case AF_INET:
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/netncp/ncp_nls.h
--- a/head/sys/netncp/ncp_nls.h Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/netncp/ncp_nls.h Wed Jul 25 16:47:10 2012 +0300
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/netncp/ncp_nls.h 236376 2012-06-01 03:59:08Z eadler $
*/
#ifndef _NETNCP_NCP_NLS_H_
#define _NETNCP_NCP_NLS_H_
@@ -52,9 +52,11 @@
#define NCP_NLS_AS_IS 1
#define NCP_NLS_AS_IS_NAME "asis"
#define NCP_NLS_KOI_866 2
+#define NCP_NLS_KOI_866_NAME "koi2cp866"
#define NCP_NLS_SE 3
-#define NCP_NLS_KOI_866_NAME "koi2cp866"
#define NCP_NLS_SE_NAME "se"
+#define NCP_NLS_DE 4
+#define NCP_NLS_DE_NAME "de"
extern struct ncp_nlstables ncp_nls; /* active nls */
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/netsmb/smb_dev.c
--- a/head/sys/netsmb/smb_dev.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/netsmb/smb_dev.c Wed Jul 25 16:47:10 2012 +0300
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/netsmb/smb_dev.c 237036 2012-06-13 22:12:10Z pjd $");
#include <sys/param.h>
#include <sys/kernel.h>
@@ -375,7 +375,7 @@
struct file* fp;
FILEDESC_SLOCK(fdp);
- if (((u_int)fd) >= fdp->fd_nfiles ||
+ if (fd < 0 || fd >= fdp->fd_nfiles ||
(fp = fdp->fd_ofiles[fd]) == NULL ||
(fp->f_flag & flag) == 0) {
FILEDESC_SUNLOCK(fdp);
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/netsmb/smb_trantcp.c
--- a/head/sys/netsmb/smb_trantcp.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/netsmb/smb_trantcp.c Wed Jul 25 16:47:10 2012 +0300
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/netsmb/smb_trantcp.c 238356 2012-07-10 21:02:59Z brueffer $");
#include <sys/param.h>
#include <sys/condvar.h>
@@ -523,8 +523,10 @@
return error;
getnanotime(&ts2);
timespecsub(&ts2, &ts1);
- if (ts2.tv_sec == 0 && ts2.tv_sec == 0)
+ if (ts2.tv_sec == 0) {
ts2.tv_sec = 1;
+ ts2.tv_nsec = 0;
+ }
nbp->nbp_timo = ts2;
timespecadd(&nbp->nbp_timo, &ts2);
timespecadd(&nbp->nbp_timo, &ts2);
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/nfsclient/nfs_bio.c
--- a/head/sys/nfsclient/nfs_bio.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/nfsclient/nfs_bio.c Wed Jul 25 16:47:10 2012 +0300
@@ -33,7 +33,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/nfsclient/nfs_bio.c 232327 2012-03-01 03:53:07Z rmacklem $");
+__FBSDID("$FreeBSD: head/sys/nfsclient/nfs_bio.c 235332 2012-05-12 12:02:51Z rmacklem $");
#include "opt_kdtrace.h"
@@ -275,7 +275,11 @@
vp = ap->a_vp;
np = VTONFS(vp);
td = curthread; /* XXX */
- cred = curthread->td_ucred; /* XXX */
+ /* Set the cred to n_writecred for the write rpcs. */
+ if (np->n_writecred != NULL)
+ cred = crhold(np->n_writecred);
+ else
+ cred = crhold(curthread->td_ucred); /* XXX */
nmp = VFSTONFS(vp->v_mount);
pages = ap->a_m;
count = ap->a_count;
@@ -339,6 +343,7 @@
iomode = NFSV3WRITE_FILESYNC;
error = (nmp->nm_rpcops->nr_writerpc)(vp, &uio, cred, &iomode, &must_commit);
+ crfree(cred);
pmap_qremove(kva, npages);
relpbuf(bp, &nfs_pbuf_freecnt);
@@ -1796,7 +1801,7 @@
* truncation point. We may have a B_DELWRI and/or B_CACHE
* buffer that now needs to be truncated.
*/
- error = vtruncbuf(vp, cred, td, nsize, biosize);
+ error = vtruncbuf(vp, cred, nsize, biosize);
lbn = nsize / biosize;
bufsize = nsize & (biosize - 1);
bp = nfs_getcacheblk(vp, lbn, bufsize, td);
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/nfsclient/nfs_node.c
--- a/head/sys/nfsclient/nfs_node.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/nfsclient/nfs_node.c Wed Jul 25 16:47:10 2012 +0300
@@ -33,7 +33,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/nfsclient/nfs_node.c 224604 2011-08-02 11:24:42Z rmacklem $");
+__FBSDID("$FreeBSD: head/sys/nfsclient/nfs_node.c 235332 2012-05-12 12:02:51Z rmacklem $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -270,6 +270,8 @@
free((caddr_t)dp2, M_NFSDIROFF);
}
}
+ if (np->n_writecred != NULL)
+ crfree(np->n_writecred);
if (np->n_fhsize > NFS_SMALLFH) {
free((caddr_t)np->n_fhp, M_NFSBIGFH);
}
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/nfsclient/nfs_subs.c
--- a/head/sys/nfsclient/nfs_subs.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/nfsclient/nfs_subs.c Wed Jul 25 16:47:10 2012 +0300
@@ -33,7 +33,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/nfsclient/nfs_subs.c 234386 2012-04-17 16:28:22Z mckusick $");
+__FBSDID("$FreeBSD: head/sys/nfsclient/nfs_subs.c 235246 2012-05-10 21:38:48Z mckusick $");
/*
* These functions support the macros and help fiddle mbuf chains for
@@ -865,7 +865,6 @@
struct buf *bp, *nbp;
struct bufobj *bo;
- MNT_ILOCK(mp);
MNT_VNODE_FOREACH_ALL(vp, mp, nvp) {
bo = &vp->v_bufobj;
vholdl(vp);
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/nfsclient/nfs_vfsops.c
--- a/head/sys/nfsclient/nfs_vfsops.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/nfsclient/nfs_vfsops.c Wed Jul 25 16:47:10 2012 +0300
@@ -33,7 +33,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/nfsclient/nfs_vfsops.c 234386 2012-04-17 16:28:22Z mckusick $");
+__FBSDID("$FreeBSD: head/sys/nfsclient/nfs_vfsops.c 235052 2012-05-05 09:34:35Z pluknet $");
#include "opt_bootp.h"
@@ -1452,6 +1452,7 @@
MNT_IUNLOCK(mp);
return (EBADF);
}
+ MNT_IUNLOCK(mp);
/*
* Force stale buffer cache information to be flushed.
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/nfsclient/nfs_vnops.c
--- a/head/sys/nfsclient/nfs_vnops.c Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/nfsclient/nfs_vnops.c Wed Jul 25 16:47:10 2012 +0300
@@ -33,7 +33,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/nfsclient/nfs_vnops.c 232821 2012-03-11 12:19:58Z kib $");
+__FBSDID("$FreeBSD: head/sys/nfsclient/nfs_vnops.c 235332 2012-05-12 12:02:51Z rmacklem $");
/*
* vnode op calls for Sun NFS version 2 and 3
@@ -507,6 +507,7 @@
struct vattr vattr;
int error;
int fmode = ap->a_mode;
+ struct ucred *cred;
if (vp->v_type != VREG && vp->v_type != VDIR && vp->v_type != VLNK)
return (EOPNOTSUPP);
@@ -563,7 +564,22 @@
}
np->n_directio_opens++;
}
+
+ /*
+ * If this is an open for writing, capture a reference to the
+ * credentials, so they can be used by nfs_putpages(). Using
+ * these write credentials is preferable to the credentials of
+ * whatever thread happens to be doing the VOP_PUTPAGES() since
+ * the write RPCs are less likely to fail with EACCES.
+ */
+ if ((fmode & FWRITE) != 0) {
+ cred = np->n_writecred;
+ np->n_writecred = crhold(ap->a_cred);
+ } else
+ cred = NULL;
mtx_unlock(&np->n_mtx);
+ if (cred != NULL)
+ crfree(cred);
vnode_create_vobject(vp, vattr.va_size, ap->a_td);
return (0);
}
diff -r 58b18bd1429e -r 4abb4d69799e head/sys/nfsclient/nfsnode.h
--- a/head/sys/nfsclient/nfsnode.h Wed Jul 25 16:45:04 2012 +0300
+++ b/head/sys/nfsclient/nfsnode.h Wed Jul 25 16:47:10 2012 +0300
@@ -30,7 +30,7 @@
* SUCH DAMAGE.
*
* @(#)nfsnode.h 8.9 (Berkeley) 5/14/95
- * $FreeBSD: head/sys/nfsclient/nfsnode.h 230394 2012-01-20 20:02:01Z jhb $
+ * $FreeBSD: head/sys/nfsclient/nfsnode.h 235332 2012-05-12 12:02:51Z rmacklem $
*/
#ifndef _NFSCLIENT_NFSNODE_H_
@@ -128,6 +128,7 @@
uint32_t n_namelen;
int n_directio_opens;
int n_directio_asyncwr;
+ struct ucred *n_writecred; /* Cred. for putpages */
};
#define n_atim n_un1.nf_atim
More information about the Zrouter-src-freebsd
mailing list