summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bin/ps/ps.13
-rw-r--r--bin/setfacl/setfacl.120
-rw-r--r--bin/sh/jobs.c2
-rw-r--r--bin/sh/mksyntax.c154
-rw-r--r--bin/sh/parser.h2
-rw-r--r--contrib/libc++/include/__config6
-rw-r--r--contrib/libc++/include/algorithm4
-rw-r--r--contrib/libc++/include/array3
-rw-r--r--contrib/libc++/include/atomic22
-rw-r--r--contrib/libc++/include/cmath90
-rw-r--r--contrib/libc++/include/functional2
-rw-r--r--contrib/libc++/include/future8
-rw-r--r--contrib/libc++/include/istream1
-rw-r--r--contrib/libc++/include/iterator4
-rw-r--r--contrib/libc++/include/limits188
-rw-r--r--contrib/libc++/include/locale20
-rw-r--r--contrib/libc++/include/memory5
-rw-r--r--contrib/libc++/include/ostream13
-rw-r--r--contrib/libc++/include/random122
-rw-r--r--contrib/libc++/include/regex21
-rw-r--r--contrib/libc++/include/string2
-rw-r--r--contrib/libc++/include/type_traits23
-rw-r--r--contrib/libc++/include/vector6
-rw-r--r--contrib/libc++/src/chrono.cpp4
-rw-r--r--contrib/libc++/src/debug.cpp2
-rw-r--r--contrib/libc++/src/exception.cpp8
-rw-r--r--contrib/libc++/src/future.cpp2
-rw-r--r--contrib/libc++/src/hash.cpp25
-rw-r--r--contrib/libc++/src/locale.cpp150
-rw-r--r--contrib/libc++/src/string.cpp136
-rw-r--r--contrib/libc++/src/thread.cpp6
-rw-r--r--lib/libc/sys/ptrace.212
-rw-r--r--libexec/rtld-elf/powerpc64/reloc.c14
-rw-r--r--sbin/ifconfig/ifieee80211.c4
-rw-r--r--share/man/man5/group.510
-rw-r--r--share/man/man9/timeout.92
-rw-r--r--sys/boot/usb/Makefile.test4
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_vfsops.h7
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c17
-rw-r--r--sys/cddl/dev/dtrace/dtrace_ioctl.c2
-rw-r--r--sys/conf/NOTES2
-rw-r--r--sys/dev/ath/if_ath_tx_ht.c17
-rw-r--r--sys/dev/bxe/if_bxe.c28
-rw-r--r--sys/dev/e1000/if_em.c25
-rw-r--r--sys/dev/e1000/if_igb.c33
-rw-r--r--sys/dev/ixgbe/ixgbe.c23
-rw-r--r--sys/dev/ixgbe/ixv.c24
-rw-r--r--sys/dev/oce/oce_if.c18
-rw-r--r--sys/dev/usb/wlan/if_uath.c38
-rw-r--r--sys/dev/usb/wlan/if_upgt.c24
-rw-r--r--sys/fs/ext2fs/ext2_vfsops.c11
-rw-r--r--sys/fs/ext2fs/ext2fs.h2
-rw-r--r--sys/fs/ext2fs/inode.h1
-rw-r--r--sys/kern/kern_exec.c2
-rw-r--r--sys/kern/kern_exit.c2
-rw-r--r--sys/kern/kern_ktr.c6
-rw-r--r--sys/kern/kern_sig.c2
-rw-r--r--sys/kern/sys_process.c2
-rw-r--r--sys/net/if_var.h53
-rw-r--r--sys/net80211/ieee80211_action.c71
-rw-r--r--sys/net80211/ieee80211_ddb.c38
-rw-r--r--sys/net80211/ieee80211_hwmp.c255
-rw-r--r--sys/net80211/ieee80211_input.c4
-rw-r--r--sys/net80211/ieee80211_ioctl.h1
-rw-r--r--sys/net80211/ieee80211_mesh.c599
-rw-r--r--sys/net80211/ieee80211_mesh.h46
-rw-r--r--sys/net80211/ieee80211_node.h2
-rw-r--r--sys/net80211/ieee80211_output.c4
-rw-r--r--sys/ofed/drivers/net/mlx4/en_tx.c20
-rw-r--r--sys/sparc64/include/vmparam.h4
-rw-r--r--sys/sys/buf_ring.h48
-rw-r--r--sys/sys/proc.h1
-rw-r--r--sys/ufs/ufs/inode.h4
-rw-r--r--usr.bin/newgrp/newgrp.113
-rw-r--r--usr.bin/newgrp/newgrp.c3
-rw-r--r--usr.bin/patch/util.c2
-rw-r--r--usr.sbin/bsdconfig/Makefile2
-rw-r--r--usr.sbin/sysrc/Makefile2
78 files changed, 1877 insertions, 681 deletions
diff --git a/bin/ps/ps.1 b/bin/ps/ps.1
index 21e8eaf..7f69137 100644
--- a/bin/ps/ps.1
+++ b/bin/ps/ps.1
@@ -29,7 +29,7 @@
.\" @(#)ps.1 8.3 (Berkeley) 4/18/94
.\" $FreeBSD$
.\"
-.Dd September 18, 2012
+.Dd February 7, 2013
.Dt PS 1
.Os
.Sh NAME
@@ -323,6 +323,7 @@ the include file
.It Dv "P_INMEM" Ta No "0x10000000" Ta "Loaded into memory"
.It Dv "P_SWAPPINGOUT" Ta No "0x20000000" Ta "Process is being swapped out"
.It Dv "P_SWAPPINGIN" Ta No "0x40000000" Ta "Process is being swapped in"
+.It Dv "P_PPTRACE" Ta No "0x80000000" Ta "Vforked child issued ptrace(PT_TRACEME)"
.El
.It Cm label
The MAC label of the process.
diff --git a/bin/setfacl/setfacl.1 b/bin/setfacl/setfacl.1
index 3d7b517..83dc41a 100644
--- a/bin/setfacl/setfacl.1
+++ b/bin/setfacl/setfacl.1
@@ -26,7 +26,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd September 2, 2012
+.Dd February 8, 2013
.Dt SETFACL 1
.Os
.Sh NAME
@@ -91,10 +91,16 @@ An error will be reported if any of
the specified files cannot have a default entry (i.e.\&
non-directories). This option is not applicable to NFSv4 ACLs.
.It Fl m Ar entries
-Modify the ACL entries on the specified files by adding new
-entries and modifying existing ACL entries with the ACL entries
-specified in
-.Ar entries .
+Modify the ACL on the specified file.
+New entries will be added, and existing entries will be modified
+according to the
+.Ar entries
+argument.
+For NFSv4 ACLs, it is recommended to use the
+.Fl a
+and
+.Fl x
+options instead.
.It Fl M Ar file
Modify the ACL entries on the specified files by adding new
ACL entries and modifying existing ACL entries with the ACL
@@ -319,9 +325,9 @@ write_data
execute
.It p
append_data
-.It d
-delete_child
.It D
+delete_child
+.It d
delete
.It a
read_attributes
diff --git a/bin/sh/jobs.c b/bin/sh/jobs.c
index d2e1d57..c86394f 100644
--- a/bin/sh/jobs.c
+++ b/bin/sh/jobs.c
@@ -1030,7 +1030,7 @@ dowait(int mode, struct job *job)
int wflags;
int restore_sigchld;
- TRACE(("dowait(%d) called\n", block));
+ TRACE(("dowait(%d, %p) called\n", mode, job));
restore_sigchld = 0;
if ((mode & DOWAIT_SIG) != 0) {
sigfillset(&mask);
diff --git a/bin/sh/mksyntax.c b/bin/sh/mksyntax.c
index 6594da3..c6bf480 100644
--- a/bin/sh/mksyntax.c
+++ b/bin/sh/mksyntax.c
@@ -103,23 +103,16 @@ static char writer[] = "\
static FILE *cfile;
static FILE *hfile;
-static const char *syntax[513];
-static int base;
-static int size; /* number of values which a char variable can have */
-static int nbits; /* number of bits in a character */
-static void filltable(const char *);
-static void init(void);
+static void add_default(void);
+static void finish(void);
+static void init(const char *);
static void add(const char *, const char *);
-static void print(const char *);
static void output_type_macros(void);
int
main(int argc __unused, char **argv __unused)
{
- char c;
- char d;
- int sign;
int i;
char buf[80];
int pos;
@@ -136,27 +129,8 @@ main(int argc __unused, char **argv __unused)
fputs(writer, hfile);
fputs(writer, cfile);
- /* Determine the characteristics of chars. */
- c = -1;
- sign = (c > 0) ? 0 : 1;
- for (nbits = 1 ; ; nbits++) {
- d = (1 << nbits) - 1;
- if (d == c)
- break;
- }
-#if 0
- printf("%s %d bit chars\n", sign? "signed" : "unsigned", nbits);
-#endif
- if (nbits > 9) {
- fputs("Characters can't have more than 9 bits\n", stderr);
- exit(2);
- }
- size = (1 << nbits) + 1;
- base = 1;
- if (sign)
- base += 1 << (nbits - 1);
-
fputs("#include <sys/cdefs.h>\n", hfile);
+ fputs("#include <limits.h>\n\n", hfile);
/* Generate the #define statements in the header file */
fputs("/* Syntax classes */\n", hfile);
@@ -177,8 +151,8 @@ main(int argc __unused, char **argv __unused)
fprintf(hfile, "/* %s */\n", is_entry[i].comment);
}
putc('\n', hfile);
- fprintf(hfile, "#define SYNBASE %d\n", base);
- fprintf(hfile, "#define PEOF %d\n\n", -base);
+ fputs("#define SYNBASE (1 - CHAR_MIN)\n", hfile);
+ fputs("#define PEOF -SYNBASE\n\n", hfile);
putc('\n', hfile);
fputs("#define BASESYNTAX (basesyntax + SYNBASE)\n", hfile);
fputs("#define DQSYNTAX (dqsyntax + SYNBASE)\n", hfile);
@@ -189,10 +163,13 @@ main(int argc __unused, char **argv __unused)
putc('\n', hfile);
/* Generate the syntax tables. */
+ fputs("#include \"parser.h\"\n", cfile);
fputs("#include \"shell.h\"\n", cfile);
fputs("#include \"syntax.h\"\n\n", cfile);
- init();
+
fputs("/* syntax table used when not in quotes */\n", cfile);
+ init("basesyntax");
+ add_default();
add("\n", "CNL");
add("\\", "CBACK");
add("'", "CSQUOTE");
@@ -201,9 +178,11 @@ main(int argc __unused, char **argv __unused)
add("$", "CVAR");
add("}", "CENDVAR");
add("<>();&| \t", "CSPCL");
- print("basesyntax");
- init();
+ finish();
+
fputs("\n/* syntax table used when in double quotes */\n", cfile);
+ init("dqsyntax");
+ add_default();
add("\n", "CNL");
add("\\", "CBACK");
add("\"", "CENDQUOTE");
@@ -212,17 +191,21 @@ main(int argc __unused, char **argv __unused)
add("}", "CENDVAR");
/* ':/' for tilde expansion, '-^]' for [a\-x] pattern ranges */
add("!*?[]=~:/-^", "CCTL");
- print("dqsyntax");
- init();
+ finish();
+
fputs("\n/* syntax table used when in single quotes */\n", cfile);
+ init("sqsyntax");
+ add_default();
add("\n", "CNL");
add("\\", "CSBACK");
add("'", "CENDQUOTE");
/* ':/' for tilde expansion, '-^]' for [a\-x] pattern ranges */
add("!*?[]=~:/-^", "CCTL");
- print("sqsyntax");
- init();
+ finish();
+
fputs("\n/* syntax table used when in arithmetic */\n", cfile);
+ init("arisyntax");
+ add_default();
add("\n", "CNL");
add("\\", "CBACK");
add("`", "CBQUOTE");
@@ -231,100 +214,95 @@ main(int argc __unused, char **argv __unused)
add("}", "CENDVAR");
add("(", "CLP");
add(")", "CRP");
- print("arisyntax");
- filltable("0");
+ finish();
+
fputs("\n/* character classification table */\n", cfile);
+ init("is_type");
add("0123456789", "ISDIGIT");
add("abcdefghijklmnopqrstuvwxyz", "ISLOWER");
add("ABCDEFGHIJKLMNOPQRSTUVWXYZ", "ISUPPER");
add("_", "ISUNDER");
add("#?$!-*@", "ISSPECL");
- print("is_type");
+ finish();
+
exit(0);
}
-
/*
- * Clear the syntax table.
+ * Output the header and declaration of a syntax table.
*/
static void
-filltable(const char *dftval)
+init(const char *name)
{
- int i;
+ fprintf(hfile, "extern const char %s[];\n", name);
+ fprintf(cfile, "const char %s[SYNBASE + CHAR_MAX + 1] = {\n", name);
+}
- for (i = 0 ; i < size ; i++)
- syntax[i] = dftval;
+
+static void
+add_one(const char *key, const char *type)
+{
+ fprintf(cfile, "\t[SYNBASE + %s] = %s,\n", key, type);
}
/*
- * Initialize the syntax table with default values.
+ * Add default values to the syntax table.
*/
static void
-init(void)
+add_default(void)
{
- filltable("CWORD");
- syntax[0] = "CEOF";
- syntax[base + CTLESC] = "CCTL";
- syntax[base + CTLVAR] = "CCTL";
- syntax[base + CTLENDVAR] = "CCTL";
- syntax[base + CTLBACKQ] = "CCTL";
- syntax[base + CTLBACKQ + CTLQUOTE] = "CCTL";
- syntax[base + CTLARI] = "CCTL";
- syntax[base + CTLENDARI] = "CCTL";
- syntax[base + CTLQUOTEMARK] = "CCTL";
- syntax[base + CTLQUOTEEND] = "CCTL";
+ add_one("PEOF", "CEOF");
+ add_one("CTLESC", "CCTL");
+ add_one("CTLVAR", "CCTL");
+ add_one("CTLENDVAR", "CCTL");
+ add_one("CTLBACKQ", "CCTL");
+ add_one("CTLBACKQ + CTLQUOTE", "CCTL");
+ add_one("CTLARI", "CCTL");
+ add_one("CTLENDARI", "CCTL");
+ add_one("CTLQUOTEMARK", "CCTL");
+ add_one("CTLQUOTEEND", "CCTL");
}
/*
- * Add entries to the syntax table.
+ * Output the footer of a syntax table.
*/
static void
-add(const char *p, const char *type)
+finish(void)
{
- while (*p)
- syntax[*p++ + base] = type;
+ fputs("};\n", cfile);
}
-
/*
- * Output the syntax table.
+ * Add entries to the syntax table.
*/
static void
-print(const char *name)
+add(const char *p, const char *type)
{
- int i;
- int col;
-
- fprintf(hfile, "extern const char %s[];\n", name);
- fprintf(cfile, "const char %s[%d] = {\n", name, size);
- col = 0;
- for (i = 0 ; i < size ; i++) {
- if (i == 0) {
- fputs(" ", cfile);
- } else if ((i & 03) == 0) {
- fputs(",\n ", cfile);
- col = 0;
- } else {
- putc(',', cfile);
- while (++col < 9 * (i & 03))
- putc(' ', cfile);
+ for (; *p; ++p) {
+ char c = *p;
+ switch (c) {
+ case '\t': c = 't'; break;
+ case '\n': c = 'n'; break;
+ case '\'': c = '\''; break;
+ case '\\': c = '\\'; break;
+
+ default:
+ fprintf(cfile, "\t[SYNBASE + '%c'] = %s,\n", c, type);
+ continue;
}
- fputs(syntax[i], cfile);
- col += strlen(syntax[i]);
+ fprintf(cfile, "\t[SYNBASE + '\\%c'] = %s,\n", c, type);
}
- fputs("\n};\n", cfile);
}
-
/*
* Output character classification macros (e.g. is_digit). If digits are
* contiguous, we can test for them quickly.
diff --git a/bin/sh/parser.h b/bin/sh/parser.h
index 9a996d0..f80d917 100644
--- a/bin/sh/parser.h
+++ b/bin/sh/parser.h
@@ -39,7 +39,7 @@
#define CTLENDVAR '\371'
#define CTLBACKQ '\372'
#define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
-/* CTLBACKQ | CTLQUOTE == '\205' */
+/* CTLBACKQ | CTLQUOTE == '\373' */
#define CTLARI '\374'
#define CTLENDARI '\375'
#define CTLQUOTEMARK '\376'
diff --git a/contrib/libc++/include/__config b/contrib/libc++/include/__config
index 203be76..8617b86 100644
--- a/contrib/libc++/include/__config
+++ b/contrib/libc++/include/__config
@@ -66,6 +66,12 @@
# endif
#endif // _WIN32
+#ifdef __linux__
+# if defined(__GNUC__) && _GNUC_VER >= 403
+# define _LIBCP_HAS_IS_BASE_OF
+# endif
+#endif
+
#ifdef __sun__
# include <sys/isa_defs.h>
# ifdef _LITTLE_ENDIAN
diff --git a/contrib/libc++/include/algorithm b/contrib/libc++/include/algorithm
index 0f6107b..e24f979 100644
--- a/contrib/libc++/include/algorithm
+++ b/contrib/libc++/include/algorithm
@@ -1528,10 +1528,10 @@ copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result)
// copy_backward
-template <class _InputIterator, class _OutputIterator>
+template <class _BidirectionalIterator, class _OutputIterator>
inline _LIBCPP_INLINE_VISIBILITY
_OutputIterator
-__copy_backward(_InputIterator __first, _InputIterator __last, _OutputIterator __result)
+__copy_backward(_BidirectionalIterator __first, _BidirectionalIterator __last, _OutputIterator __result)
{
while (__first != __last)
*--__result = *--__last;
diff --git a/contrib/libc++/include/array b/contrib/libc++/include/array
index 029bfd0..f4a3020 100644
--- a/contrib/libc++/include/array
+++ b/contrib/libc++/include/array
@@ -310,6 +310,7 @@ _LIBCPP_INLINE_VISIBILITY inline
_Tp&
get(array<_Tp, _Size>& __a) _NOEXCEPT
{
+ static_assert(_Ip < _Size, "Index out of bounds in std::get<> (std::array)");
return __a[_Ip];
}
@@ -318,6 +319,7 @@ _LIBCPP_INLINE_VISIBILITY inline
const _Tp&
get(const array<_Tp, _Size>& __a) _NOEXCEPT
{
+ static_assert(_Ip < _Size, "Index out of bounds in std::get<> (const std::array)");
return __a[_Ip];
}
@@ -328,6 +330,7 @@ _LIBCPP_INLINE_VISIBILITY inline
_Tp&&
get(array<_Tp, _Size>&& __a) _NOEXCEPT
{
+ static_assert(_Ip < _Size, "Index out of bounds in std::get<> (std::array &&)");
return _VSTD::move(__a[_Ip]);
}
diff --git a/contrib/libc++/include/atomic b/contrib/libc++/include/atomic
index 6dffdb2..db67e76 100644
--- a/contrib/libc++/include/atomic
+++ b/contrib/libc++/include/atomic
@@ -33,6 +33,7 @@ template <class T> T kill_dependency(T y) noexcept;
// lock-free property
+#define ATOMIC_BOOL_LOCK_FREE unspecified
#define ATOMIC_CHAR_LOCK_FREE unspecified
#define ATOMIC_CHAR16_T_LOCK_FREE unspecified
#define ATOMIC_CHAR32_T_LOCK_FREE unspecified
@@ -41,6 +42,7 @@ template <class T> T kill_dependency(T y) noexcept;
#define ATOMIC_INT_LOCK_FREE unspecified
#define ATOMIC_LONG_LOCK_FREE unspecified
#define ATOMIC_LLONG_LOCK_FREE unspecified
+#define ATOMIC_POINTER_LOCK_FREE unspecified
// flag type and operations
@@ -472,6 +474,7 @@ template <class T>
// Atomics for standard typedef types
+typedef atomic<bool> atomic_bool;
typedef atomic<char> atomic_char;
typedef atomic<signed char> atomic_schar;
typedef atomic<unsigned char> atomic_uchar;
@@ -1454,6 +1457,7 @@ atomic_signal_fence(memory_order __m) _NOEXCEPT
// Atomics for standard typedef types
+typedef atomic<bool> atomic_bool;
typedef atomic<char> atomic_char;
typedef atomic<signed char> atomic_schar;
typedef atomic<unsigned char> atomic_uchar;
@@ -1499,14 +1503,16 @@ typedef atomic<uintmax_t> atomic_uintmax_t;
// lock-free property
-#define ATOMIC_CHAR_LOCK_FREE 0
-#define ATOMIC_CHAR16_T_LOCK_FREE 0
-#define ATOMIC_CHAR32_T_LOCK_FREE 0
-#define ATOMIC_WCHAR_T_LOCK_FREE 0
-#define ATOMIC_SHORT_LOCK_FREE 0
-#define ATOMIC_INT_LOCK_FREE 0
-#define ATOMIC_LONG_LOCK_FREE 0
-#define ATOMIC_LLONG_LOCK_FREE 0
+#define ATOMIC_BOOL_LOCK_FREE __GCC_ATOMIC_BOOL_LOCK_FREE
+#define ATOMIC_CHAR_LOCK_FREE __GCC_ATOMIC_CHAR_LOCK_FREE
+#define ATOMIC_CHAR16_T_LOCK_FREE __GCC_ATOMIC_CHAR16_T_LOCK_FREE
+#define ATOMIC_CHAR32_T_LOCK_FREE __GCC_ATOMIC_CHAR32_T_LOCK_FREE
+#define ATOMIC_WCHAR_T_LOCK_FREE __GCC_ATOMIC_WCHAR_T_LOCK_FREE
+#define ATOMIC_SHORT_LOCK_FREE __GCC_ATOMIC_SHORT_LOCK_FREE
+#define ATOMIC_INT_LOCK_FREE __GCC_ATOMIC_INT_LOCK_FREE
+#define ATOMIC_LONG_LOCK_FREE __GCC_ATOMIC_LONG_LOCK_FREE
+#define ATOMIC_LLONG_LOCK_FREE __GCC_ATOMIC_LLONG_LOCK_FREE
+#define ATOMIC_POINTER_LOCK_FREE __GCC_ATOMIC_POINTER_LOCK_FREE
#endif // !__has_feature(cxx_atomic)
diff --git a/contrib/libc++/include/cmath b/contrib/libc++/include/cmath
index d3fbfe6..bd60344 100644
--- a/contrib/libc++/include/cmath
+++ b/contrib/libc++/include/cmath
@@ -137,21 +137,21 @@ long double tanhl(long double x);
// C99
-bool signbit(floating_point x);
+bool signbit(arithmetic x);
-int fpclassify(floating_point x);
+int fpclassify(arithmetic x);
-bool isfinite(floating_point x);
-bool isinf(floating_point x);
-bool isnan(floating_point x);
-bool isnormal(floating_point x);
+bool isfinite(arithmetic x);
+bool isinf(arithmetic x);
+bool isnan(arithmetic x);
+bool isnormal(arithmetic x);
-bool isgreater(floating_point x, floating_point y);
-bool isgreaterequal(floating_point x, floating_point y);
-bool isless(floating_point x, floating_point y);
-bool islessequal(floating_point x, floating_point y);
-bool islessgreater(floating_point x, floating_point y);
-bool isunordered(floating_point x, floating_point y);
+bool isgreater(arithmetic x, arithmetic y);
+bool isgreaterequal(arithmetic x, arithmetic y);
+bool isless(arithmetic x, arithmetic y);
+bool islessequal(arithmetic x, arithmetic y);
+bool islessgreater(arithmetic x, arithmetic y);
+bool isunordered(arithmetic x, arithmetic y);
floating_point acosh (arithmetic x);
float acoshf(float x);
@@ -325,10 +325,10 @@ __libcpp_signbit(_A1 __x) _NOEXCEPT
template <class _A1>
inline _LIBCPP_INLINE_VISIBILITY
-typename std::enable_if<std::is_floating_point<_A1>::value, bool>::type
+typename std::enable_if<std::is_arithmetic<_A1>::value, bool>::type
signbit(_A1 __x) _NOEXCEPT
{
- return __libcpp_signbit(__x);
+ return __libcpp_signbit((typename std::__promote<_A1>::type)__x);
}
#endif // signbit
@@ -349,10 +349,10 @@ __libcpp_fpclassify(_A1 __x) _NOEXCEPT
template <class _A1>
inline _LIBCPP_INLINE_VISIBILITY
-typename std::enable_if<std::is_floating_point<_A1>::value, int>::type
+typename std::enable_if<std::is_arithmetic<_A1>::value, int>::type
fpclassify(_A1 __x) _NOEXCEPT
{
- return __libcpp_fpclassify(__x);
+ return __libcpp_fpclassify((typename std::__promote<_A1>::type)__x);
}
#endif // fpclassify
@@ -373,10 +373,10 @@ __libcpp_isfinite(_A1 __x) _NOEXCEPT
template <class _A1>
inline _LIBCPP_INLINE_VISIBILITY
-typename std::enable_if<std::is_floating_point<_A1>::value, bool>::type
+typename std::enable_if<std::is_arithmetic<_A1>::value, bool>::type
isfinite(_A1 __x) _NOEXCEPT
{
- return __libcpp_isfinite(__x);
+ return __libcpp_isfinite((typename std::__promote<_A1>::type)__x);
}
#endif // isfinite
@@ -397,10 +397,10 @@ __libcpp_isinf(_A1 __x) _NOEXCEPT
template <class _A1>
inline _LIBCPP_INLINE_VISIBILITY
-typename std::enable_if<std::is_floating_point<_A1>::value, bool>::type
+typename std::enable_if<std::is_arithmetic<_A1>::value, bool>::type
isinf(_A1 __x) _NOEXCEPT
{
- return __libcpp_isinf(__x);
+ return __libcpp_isinf((typename std::__promote<_A1>::type)__x);
}
#endif // isinf
@@ -421,10 +421,10 @@ __libcpp_isnan(_A1 __x) _NOEXCEPT
template <class _A1>
inline _LIBCPP_INLINE_VISIBILITY
-typename std::enable_if<std::is_floating_point<_A1>::value, bool>::type
+typename std::enable_if<std::is_arithmetic<_A1>::value, bool>::type
isnan(_A1 __x) _NOEXCEPT
{
- return __libcpp_isnan(__x);
+ return __libcpp_isnan((typename std::__promote<_A1>::type)__x);
}
#endif // isnan
@@ -445,10 +445,10 @@ __libcpp_isnormal(_A1 __x) _NOEXCEPT
template <class _A1>
inline _LIBCPP_INLINE_VISIBILITY
-typename std::enable_if<std::is_floating_point<_A1>::value, bool>::type
+typename std::enable_if<std::is_arithmetic<_A1>::value, bool>::type
isnormal(_A1 __x) _NOEXCEPT
{
- return __libcpp_isnormal(__x);
+ return __libcpp_isnormal((typename std::__promote<_A1>::type)__x);
}
#endif // isnormal
@@ -471,13 +471,14 @@ template <class _A1, class _A2>
inline _LIBCPP_INLINE_VISIBILITY
typename std::enable_if
<
- std::is_floating_point<_A1>::value &&
- std::is_floating_point<_A2>::value,
+ std::is_arithmetic<_A1>::value &&
+ std::is_arithmetic<_A2>::value,
bool
>::type
isgreater(_A1 __x, _A2 __y) _NOEXCEPT
{
- return __libcpp_isgreater(__x, __y);
+ typedef typename std::__promote<_A1, _A2>::type type;
+ return __libcpp_isgreater((type)__x, (type)__y);
}
#endif // isgreater
@@ -500,13 +501,14 @@ template <class _A1, class _A2>
inline _LIBCPP_INLINE_VISIBILITY
typename std::enable_if
<
- std::is_floating_point<_A1>::value &&
- std::is_floating_point<_A2>::value,
+ std::is_arithmetic<_A1>::value &&
+ std::is_arithmetic<_A2>::value,
bool
>::type
isgreaterequal(_A1 __x, _A2 __y) _NOEXCEPT
{
- return __libcpp_isgreaterequal(__x, __y);
+ typedef typename std::__promote<_A1, _A2>::type type;
+ return __libcpp_isgreaterequal((type)__x, (type)__y);
}
#endif // isgreaterequal
@@ -529,13 +531,14 @@ template <class _A1, class _A2>
inline _LIBCPP_INLINE_VISIBILITY
typename std::enable_if
<
- std::is_floating_point<_A1>::value &&
- std::is_floating_point<_A2>::value,
+ std::is_arithmetic<_A1>::value &&
+ std::is_arithmetic<_A2>::value,
bool
>::type
isless(_A1 __x, _A2 __y) _NOEXCEPT
{
- return __libcpp_isless(__x, __y);
+ typedef typename std::__promote<_A1, _A2>::type type;
+ return __libcpp_isless((type)__x, (type)__y);
}
#endif // isless
@@ -558,13 +561,14 @@ template <class _A1, class _A2>
inline _LIBCPP_INLINE_VISIBILITY
typename std::enable_if
<
- std::is_floating_point<_A1>::value &&
- std::is_floating_point<_A2>::value,
+ std::is_arithmetic<_A1>::value &&
+ std::is_arithmetic<_A2>::value,
bool
>::type
islessequal(_A1 __x, _A2 __y) _NOEXCEPT
{
- return __libcpp_islessequal(__x, __y);
+ typedef typename std::__promote<_A1, _A2>::type type;
+ return __libcpp_islessequal((type)__x, (type)__y);
}
#endif // islessequal
@@ -587,13 +591,14 @@ template <class _A1, class _A2>
inline _LIBCPP_INLINE_VISIBILITY
typename std::enable_if
<
- std::is_floating_point<_A1>::value &&
- std::is_floating_point<_A2>::value,
+ std::is_arithmetic<_A1>::value &&
+ std::is_arithmetic<_A2>::value,
bool
>::type
islessgreater(_A1 __x, _A2 __y) _NOEXCEPT
{
- return __libcpp_islessgreater(__x, __y);
+ typedef typename std::__promote<_A1, _A2>::type type;
+ return __libcpp_islessgreater((type)__x, (type)__y);
}
#endif // islessgreater
@@ -616,13 +621,14 @@ template <class _A1, class _A2>
inline _LIBCPP_INLINE_VISIBILITY
typename std::enable_if
<
- std::is_floating_point<_A1>::value &&
- std::is_floating_point<_A2>::value,
+ std::is_arithmetic<_A1>::value &&
+ std::is_arithmetic<_A2>::value,
bool
>::type
isunordered(_A1 __x, _A2 __y) _NOEXCEPT
{
- return __libcpp_isunordered(__x, __y);
+ typedef typename std::__promote<_A1, _A2>::type type;
+ return __libcpp_isunordered((type)__x, (type)__y);
}
#endif // isunordered
diff --git a/contrib/libc++/include/functional b/contrib/libc++/include/functional
index ec5c5e5..3bee1ed 100644
--- a/contrib/libc++/include/functional
+++ b/contrib/libc++/include/functional
@@ -1088,7 +1088,7 @@ class _LIBCPP_VISIBLE function<_Rp(_ArgTypes...)>
public __function::__maybe_derive_from_binary_function<_Rp(_ArgTypes...)>
{
typedef __function::__base<_Rp(_ArgTypes...)> __base;
- aligned_storage<3*sizeof(void*)>::type __buf_;
+ typename aligned_storage<3*sizeof(void*)>::type __buf_;
__base* __f_;
template <class _Fp>
diff --git a/contrib/libc++/include/future b/contrib/libc++/include/future
index cf552a9..fa605e7 100644
--- a/contrib/libc++/include/future
+++ b/contrib/libc++/include/future
@@ -470,7 +470,11 @@ public:
{return (__state_ & __constructed) || (__exception_ != nullptr);}
_LIBCPP_INLINE_VISIBILITY
- void __set_future_attached() {__state_ |= __future_attached;}
+ void __set_future_attached()
+ {
+ lock_guard<mutex> __lk(__mut_);
+ __state_ |= __future_attached;
+ }
_LIBCPP_INLINE_VISIBILITY
bool __has_future_attached() const {return __state_ & __future_attached;}
@@ -1753,7 +1757,7 @@ template<class _Rp, class ..._ArgTypes>
class __packaged_task_function<_Rp(_ArgTypes...)>
{
typedef __packaged_task_base<_Rp(_ArgTypes...)> __base;
- aligned_storage<3*sizeof(void*)>::type __buf_;
+ typename aligned_storage<3*sizeof(void*)>::type __buf_;
__base* __f_;
public:
diff --git a/contrib/libc++/include/istream b/contrib/libc++/include/istream
index dc1c52b..3979e14 100644
--- a/contrib/libc++/include/istream
+++ b/contrib/libc++/include/istream
@@ -1243,6 +1243,7 @@ template<class _CharT, class _Traits>
streamsize
basic_istream<_CharT, _Traits>::readsome(char_type* __s, streamsize __n)
{
+ __gc_ = 0;
streamsize __c = this->rdbuf()->in_avail();
switch (__c)
{
diff --git a/contrib/libc++/include/iterator b/contrib/libc++/include/iterator
index bc0ce47..b23310b 100644
--- a/contrib/libc++/include/iterator
+++ b/contrib/libc++/include/iterator
@@ -822,9 +822,9 @@ private:
public:
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR istreambuf_iterator() _NOEXCEPT : __sbuf_(0) {}
_LIBCPP_INLINE_VISIBILITY istreambuf_iterator(istream_type& __s) _NOEXCEPT
- : __sbuf_(__s.rdbuf()) {__test_for_eof();}
+ : __sbuf_(__s.rdbuf()) {}
_LIBCPP_INLINE_VISIBILITY istreambuf_iterator(streambuf_type* __s) _NOEXCEPT
- : __sbuf_(__s) {__test_for_eof();}
+ : __sbuf_(__s) {}
_LIBCPP_INLINE_VISIBILITY istreambuf_iterator(const __proxy& __p) _NOEXCEPT
: __sbuf_(__p.__sbuf_) {}
diff --git a/contrib/libc++/include/limits b/contrib/libc++/include/limits
index 68e6336..f089a79 100644
--- a/contrib/libc++/include/limits
+++ b/contrib/libc++/include/limits
@@ -479,6 +479,53 @@ public:
};
template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<_Tp>::is_specialized;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const int numeric_limits<_Tp>::digits;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const int numeric_limits<_Tp>::digits10;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const int numeric_limits<_Tp>::max_digits10;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<_Tp>::is_signed;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<_Tp>::is_integer;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<_Tp>::is_exact;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const int numeric_limits<_Tp>::radix;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const int numeric_limits<_Tp>::min_exponent;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const int numeric_limits<_Tp>::min_exponent10;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const int numeric_limits<_Tp>::max_exponent;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const int numeric_limits<_Tp>::max_exponent10;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<_Tp>::has_infinity;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<_Tp>::has_quiet_NaN;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<_Tp>::has_signaling_NaN;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const float_denorm_style numeric_limits<_Tp>::has_denorm;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<_Tp>::has_denorm_loss;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<_Tp>::is_iec559;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<_Tp>::is_bounded;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<_Tp>::is_modulo;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<_Tp>::traps;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<_Tp>::tinyness_before;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const float_round_style numeric_limits<_Tp>::round_style;
+
+template <class _Tp>
class _LIBCPP_VISIBLE numeric_limits<const _Tp>
: private numeric_limits<_Tp>
{
@@ -525,6 +572,53 @@ public:
};
template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<const _Tp>::is_specialized;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const int numeric_limits<const _Tp>::digits;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const int numeric_limits<const _Tp>::digits10;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const int numeric_limits<const _Tp>::max_digits10;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<const _Tp>::is_signed;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<const _Tp>::is_integer;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<const _Tp>::is_exact;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const int numeric_limits<const _Tp>::radix;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const int numeric_limits<const _Tp>::min_exponent;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const int numeric_limits<const _Tp>::min_exponent10;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const int numeric_limits<const _Tp>::max_exponent;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const int numeric_limits<const _Tp>::max_exponent10;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<const _Tp>::has_infinity;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<const _Tp>::has_quiet_NaN;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<const _Tp>::has_signaling_NaN;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const float_denorm_style numeric_limits<const _Tp>::has_denorm;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<const _Tp>::has_denorm_loss;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<const _Tp>::is_iec559;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<const _Tp>::is_bounded;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<const _Tp>::is_modulo;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<const _Tp>::traps;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<const _Tp>::tinyness_before;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const float_round_style numeric_limits<const _Tp>::round_style;
+
+template <class _Tp>
class _LIBCPP_VISIBLE numeric_limits<volatile _Tp>
: private numeric_limits<_Tp>
{
@@ -571,6 +665,53 @@ public:
};
template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<volatile _Tp>::is_specialized;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const int numeric_limits<volatile _Tp>::digits;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const int numeric_limits<volatile _Tp>::digits10;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const int numeric_limits<volatile _Tp>::max_digits10;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<volatile _Tp>::is_signed;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<volatile _Tp>::is_integer;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<volatile _Tp>::is_exact;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const int numeric_limits<volatile _Tp>::radix;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const int numeric_limits<volatile _Tp>::min_exponent;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const int numeric_limits<volatile _Tp>::min_exponent10;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const int numeric_limits<volatile _Tp>::max_exponent;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const int numeric_limits<volatile _Tp>::max_exponent10;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<volatile _Tp>::has_infinity;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<volatile _Tp>::has_quiet_NaN;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<volatile _Tp>::has_signaling_NaN;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const float_denorm_style numeric_limits<volatile _Tp>::has_denorm;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<volatile _Tp>::has_denorm_loss;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<volatile _Tp>::is_iec559;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<volatile _Tp>::is_bounded;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<volatile _Tp>::is_modulo;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<volatile _Tp>::traps;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<volatile _Tp>::tinyness_before;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const float_round_style numeric_limits<volatile _Tp>::round_style;
+
+template <class _Tp>
class _LIBCPP_VISIBLE numeric_limits<const volatile _Tp>
: private numeric_limits<_Tp>
{
@@ -616,6 +757,53 @@ public:
static _LIBCPP_CONSTEXPR const float_round_style round_style = __base::round_style;
};
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<const volatile _Tp>::is_specialized;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const int numeric_limits<const volatile _Tp>::digits;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const int numeric_limits<const volatile _Tp>::digits10;
+template <class _Tp>
+ const int numeric_limits<const volatile _Tp>::max_digits10;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<const volatile _Tp>::is_signed;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<const volatile _Tp>::is_integer;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<const volatile _Tp>::is_exact;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const int numeric_limits<const volatile _Tp>::radix;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const int numeric_limits<const volatile _Tp>::min_exponent;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const int numeric_limits<const volatile _Tp>::min_exponent10;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const int numeric_limits<const volatile _Tp>::max_exponent;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const int numeric_limits<const volatile _Tp>::max_exponent10;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<const volatile _Tp>::has_infinity;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<const volatile _Tp>::has_quiet_NaN;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<const volatile _Tp>::has_signaling_NaN;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const float_denorm_style numeric_limits<const volatile _Tp>::has_denorm;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<const volatile _Tp>::has_denorm_loss;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<const volatile _Tp>::is_iec559;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<const volatile _Tp>::is_bounded;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<const volatile _Tp>::is_modulo;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<const volatile _Tp>::traps;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const bool numeric_limits<const volatile _Tp>::tinyness_before;
+template <class _Tp>
+ _LIBCPP_CONSTEXPR const float_round_style numeric_limits<const volatile _Tp>::round_style;
+
_LIBCPP_END_NAMESPACE_STD
#endif // _LIBCPP_LIMITS
diff --git a/contrib/libc++/include/locale b/contrib/libc++/include/locale
index f04a36b..9189375 100644
--- a/contrib/libc++/include/locale
+++ b/contrib/libc++/include/locale
@@ -354,7 +354,7 @@ size_t __mbsrtowcs_l(wchar_t *__dest, const char **__src, size_t __len,
#endif
}
-_LIBCPP_ALWAYS_INLINE inline
+inline
int __sprintf_l(char *__s, locale_t __l, const char *__format, ...) {
va_list __va;
va_start(__va, __format);
@@ -368,7 +368,7 @@ int __sprintf_l(char *__s, locale_t __l, const char *__format, ...) {
return __res;
}
-_LIBCPP_ALWAYS_INLINE inline
+inline
int __snprintf_l(char *__s, size_t __n, locale_t __l, const char *__format, ...) {
va_list __va;
va_start(__va, __format);
@@ -382,7 +382,7 @@ int __snprintf_l(char *__s, size_t __n, locale_t __l, const char *__format, ...)
return __res;
}
-_LIBCPP_ALWAYS_INLINE inline
+inline
int __asprintf_l(char **__s, locale_t __l, const char *__format, ...) {
va_list __va;
va_start(__va, __format);
@@ -396,7 +396,7 @@ int __asprintf_l(char **__s, locale_t __l, const char *__format, ...) {
return __res;
}
-_LIBCPP_ALWAYS_INLINE inline
+inline
int __sscanf_l(const char *__s, locale_t __l, const char *__format, ...) {
va_list __va;
va_start(__va, __format);
@@ -830,11 +830,11 @@ __num_get_signed_integral(const char* __a, const char* __a_end,
{
if (__a != __a_end)
{
- int __save_errno = errno;
+ typename remove_reference<decltype(errno)>::type __save_errno = errno;
errno = 0;
char *__p2;
long long __ll = strtoll_l(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE);
- int __current_errno = errno;
+ typename remove_reference<decltype(errno)>::type __current_errno = errno;
if (__current_errno == 0)
errno = __save_errno;
if (__p2 != __a_end)
@@ -870,11 +870,11 @@ __num_get_unsigned_integral(const char* __a, const char* __a_end,
__err = ios_base::failbit;
return 0;
}
- int __save_errno = errno;
+ typename remove_reference<decltype(errno)>::type __save_errno = errno;
errno = 0;
char *__p2;
unsigned long long __ll = strtoull_l(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE);
- int __current_errno = errno;
+ typename remove_reference<decltype(errno)>::type __current_errno = errno;
if (__current_errno == 0)
errno = __save_errno;
if (__p2 != __a_end)
@@ -2895,6 +2895,10 @@ template <class _CharT, bool _International>
locale::id
moneypunct<_CharT, _International>::id;
+template <class _CharT, bool _International>
+const bool
+moneypunct<_CharT, _International>::intl;
+
_LIBCPP_EXTERN_TEMPLATE(class moneypunct<char, false>)
_LIBCPP_EXTERN_TEMPLATE(class moneypunct<char, true>)
_LIBCPP_EXTERN_TEMPLATE(class moneypunct<wchar_t, false>)
diff --git a/contrib/libc++/include/memory b/contrib/libc++/include/memory
index 4c12ad9..f80d699 100644
--- a/contrib/libc++/include/memory
+++ b/contrib/libc++/include/memory
@@ -1571,7 +1571,10 @@ struct _LIBCPP_VISIBLE allocator_traits
__construct_backward(allocator_type& __a, _Ptr __begin1, _Ptr __end1, _Ptr& __end2)
{
while (__end1 != __begin1)
- construct(__a, _VSTD::__to_raw_pointer(--__end2), _VSTD::move_if_noexcept(*--__end1));
+ {
+ construct(__a, _VSTD::__to_raw_pointer(__end2-1), _VSTD::move_if_noexcept(*--__end1));
+ --__end2;
+ }
}
template <class _Tp>
diff --git a/contrib/libc++/include/ostream b/contrib/libc++/include/ostream
index 9d26a41..b3b6df5 100644
--- a/contrib/libc++/include/ostream
+++ b/contrib/libc++/include/ostream
@@ -1100,17 +1100,8 @@ basic_ostream<_CharT, _Traits>::write(const char_type* __s, streamsize __n)
sentry __sen(*this);
if (__sen && __n)
{
- typedef ostreambuf_iterator<_CharT, _Traits> _Op;
- _Op __o(*this);
- for (; __n; --__n, ++__o, ++__s)
- {
- *__o = *__s;
- if (__o.failed())
- {
- this->setstate(ios_base::badbit);
- break;
- }
- }
+ if (this->rdbuf()->sputn(__s, __n) != __n)
+ this->setstate(ios_base::badbit);
}
#ifndef _LIBCPP_NO_EXCEPTIONS
}
diff --git a/contrib/libc++/include/random b/contrib/libc++/include/random
index d838289..04d942b 100644
--- a/contrib/libc++/include/random
+++ b/contrib/libc++/include/random
@@ -1931,6 +1931,22 @@ private:
};
template <class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>
+ _LIBCPP_CONSTEXPR const typename linear_congruential_engine<_UIntType, __a, __c, __m>::result_type
+ linear_congruential_engine<_UIntType, __a, __c, __m>::multiplier;
+
+template <class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>
+ _LIBCPP_CONSTEXPR const typename linear_congruential_engine<_UIntType, __a, __c, __m>::result_type
+ linear_congruential_engine<_UIntType, __a, __c, __m>::increment;
+
+template <class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>
+ _LIBCPP_CONSTEXPR const typename linear_congruential_engine<_UIntType, __a, __c, __m>::result_type
+ linear_congruential_engine<_UIntType, __a, __c, __m>::modulus;
+
+template <class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>
+ _LIBCPP_CONSTEXPR const typename linear_congruential_engine<_UIntType, __a, __c, __m>::result_type
+ linear_congruential_engine<_UIntType, __a, __c, __m>::default_seed;
+
+template <class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>
template<class _Sseq>
void
linear_congruential_engine<_UIntType, __a, __c, __m>::__seed(_Sseq& __q,
@@ -2230,6 +2246,90 @@ private:
template <class _UIntType, size_t __w, size_t __n, size_t __m, size_t __r,
_UIntType __a, size_t __u, _UIntType __d, size_t __s,
_UIntType __b, size_t __t, _UIntType __c, size_t __l, _UIntType __f>
+ _LIBCPP_CONSTEXPR const size_t
+ mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::word_size;
+
+template <class _UIntType, size_t __w, size_t __n, size_t __m, size_t __r,
+ _UIntType __a, size_t __u, _UIntType __d, size_t __s,
+ _UIntType __b, size_t __t, _UIntType __c, size_t __l, _UIntType __f>
+ _LIBCPP_CONSTEXPR const size_t
+ mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::state_size;
+
+template <class _UIntType, size_t __w, size_t __n, size_t __m, size_t __r,
+ _UIntType __a, size_t __u, _UIntType __d, size_t __s,
+ _UIntType __b, size_t __t, _UIntType __c, size_t __l, _UIntType __f>
+ _LIBCPP_CONSTEXPR const size_t
+ mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::shift_size;
+
+template <class _UIntType, size_t __w, size_t __n, size_t __m, size_t __r,
+ _UIntType __a, size_t __u, _UIntType __d, size_t __s,
+ _UIntType __b, size_t __t, _UIntType __c, size_t __l, _UIntType __f>
+ _LIBCPP_CONSTEXPR const size_t
+ mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::mask_bits;
+
+template <class _UIntType, size_t __w, size_t __n, size_t __m, size_t __r,
+ _UIntType __a, size_t __u, _UIntType __d, size_t __s,
+ _UIntType __b, size_t __t, _UIntType __c, size_t __l, _UIntType __f>
+ _LIBCPP_CONSTEXPR const typename mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::result_type
+ mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::xor_mask;
+
+template <class _UIntType, size_t __w, size_t __n, size_t __m, size_t __r,
+ _UIntType __a, size_t __u, _UIntType __d, size_t __s,
+ _UIntType __b, size_t __t, _UIntType __c, size_t __l, _UIntType __f>
+ _LIBCPP_CONSTEXPR const size_t
+ mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::tempering_u;
+
+template <class _UIntType, size_t __w, size_t __n, size_t __m, size_t __r,
+ _UIntType __a, size_t __u, _UIntType __d, size_t __s,
+ _UIntType __b, size_t __t, _UIntType __c, size_t __l, _UIntType __f>
+ _LIBCPP_CONSTEXPR const typename mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::result_type
+ mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::tempering_d;
+
+template <class _UIntType, size_t __w, size_t __n, size_t __m, size_t __r,
+ _UIntType __a, size_t __u, _UIntType __d, size_t __s,
+ _UIntType __b, size_t __t, _UIntType __c, size_t __l, _UIntType __f>
+ _LIBCPP_CONSTEXPR const size_t
+ mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::tempering_s;
+
+template <class _UIntType, size_t __w, size_t __n, size_t __m, size_t __r,
+ _UIntType __a, size_t __u, _UIntType __d, size_t __s,
+ _UIntType __b, size_t __t, _UIntType __c, size_t __l, _UIntType __f>
+ _LIBCPP_CONSTEXPR const typename mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::result_type
+ mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::tempering_b;
+
+template <class _UIntType, size_t __w, size_t __n, size_t __m, size_t __r,
+ _UIntType __a, size_t __u, _UIntType __d, size_t __s,
+ _UIntType __b, size_t __t, _UIntType __c, size_t __l, _UIntType __f>
+ _LIBCPP_CONSTEXPR const size_t
+ mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::tempering_t;
+
+template <class _UIntType, size_t __w, size_t __n, size_t __m, size_t __r,
+ _UIntType __a, size_t __u, _UIntType __d, size_t __s,
+ _UIntType __b, size_t __t, _UIntType __c, size_t __l, _UIntType __f>
+ _LIBCPP_CONSTEXPR const typename mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::result_type
+ mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::tempering_c;
+
+template <class _UIntType, size_t __w, size_t __n, size_t __m, size_t __r,
+ _UIntType __a, size_t __u, _UIntType __d, size_t __s,
+ _UIntType __b, size_t __t, _UIntType __c, size_t __l, _UIntType __f>
+ _LIBCPP_CONSTEXPR const size_t
+ mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::tempering_l;
+
+template <class _UIntType, size_t __w, size_t __n, size_t __m, size_t __r,
+ _UIntType __a, size_t __u, _UIntType __d, size_t __s,
+ _UIntType __b, size_t __t, _UIntType __c, size_t __l, _UIntType __f>
+ _LIBCPP_CONSTEXPR const typename mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::result_type
+ mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::initialization_multiplier;
+
+template <class _UIntType, size_t __w, size_t __n, size_t __m, size_t __r,
+ _UIntType __a, size_t __u, _UIntType __d, size_t __s,
+ _UIntType __b, size_t __t, _UIntType __c, size_t __l, _UIntType __f>
+ _LIBCPP_CONSTEXPR const typename mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::result_type
+ mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::default_seed;
+
+template <class _UIntType, size_t __w, size_t __n, size_t __m, size_t __r,
+ _UIntType __a, size_t __u, _UIntType __d, size_t __s,
+ _UIntType __b, size_t __t, _UIntType __c, size_t __l, _UIntType __f>
void
mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b,
__t, __c, __l, __f>::seed(result_type __sd)
@@ -2552,6 +2652,19 @@ private:
};
template<class _UIntType, size_t __w, size_t __s, size_t __r>
+ _LIBCPP_CONSTEXPR const size_t subtract_with_carry_engine<_UIntType, __w, __s, __r>::word_size;
+
+template<class _UIntType, size_t __w, size_t __s, size_t __r>
+ _LIBCPP_CONSTEXPR const size_t subtract_with_carry_engine<_UIntType, __w, __s, __r>::short_lag;
+
+template<class _UIntType, size_t __w, size_t __s, size_t __r>
+ _LIBCPP_CONSTEXPR const size_t subtract_with_carry_engine<_UIntType, __w, __s, __r>::long_lag;
+
+template<class _UIntType, size_t __w, size_t __s, size_t __r>
+ _LIBCPP_CONSTEXPR const typename subtract_with_carry_engine<_UIntType, __w, __s, __r>::result_type
+ subtract_with_carry_engine<_UIntType, __w, __s, __r>::default_seed;
+
+template<class _UIntType, size_t __w, size_t __s, size_t __r>
void
subtract_with_carry_engine<_UIntType, __w, __s, __r>::seed(result_type __sd,
integral_constant<unsigned, 1>)
@@ -2823,6 +2936,12 @@ public:
};
template<class _Engine, size_t __p, size_t __r>
+ _LIBCPP_CONSTEXPR const size_t discard_block_engine<_Engine, __p, __r>::block_size;
+
+template<class _Engine, size_t __p, size_t __r>
+ _LIBCPP_CONSTEXPR const size_t discard_block_engine<_Engine, __p, __r>::used_block;
+
+template<class _Engine, size_t __p, size_t __r>
typename discard_block_engine<_Engine, __p, __r>::result_type
discard_block_engine<_Engine, __p, __r>::operator()()
{
@@ -3314,6 +3433,9 @@ private:
}
};
+template<class _Engine, size_t __k>
+ _LIBCPP_CONSTEXPR const size_t shuffle_order_engine<_Engine, __k>::table_size;
+
template<class _Eng, size_t _Kp>
bool
operator==(
diff --git a/contrib/libc++/include/regex b/contrib/libc++/include/regex
index 7505f2e..982500f 100644
--- a/contrib/libc++/include/regex
+++ b/contrib/libc++/include/regex
@@ -2843,6 +2843,27 @@ private:
};
template <class _CharT, class _Traits>
+ const regex_constants::syntax_option_type basic_regex<_CharT, _Traits>::icase;
+template <class _CharT, class _Traits>
+ const regex_constants::syntax_option_type basic_regex<_CharT, _Traits>::nosubs;
+template <class _CharT, class _Traits>
+ const regex_constants::syntax_option_type basic_regex<_CharT, _Traits>::optimize;
+template <class _CharT, class _Traits>
+ const regex_constants::syntax_option_type basic_regex<_CharT, _Traits>::collate;
+template <class _CharT, class _Traits>
+ const regex_constants::syntax_option_type basic_regex<_CharT, _Traits>::ECMAScript;
+template <class _CharT, class _Traits>
+ const regex_constants::syntax_option_type basic_regex<_CharT, _Traits>::basic;
+template <class _CharT, class _Traits>
+ const regex_constants::syntax_option_type basic_regex<_CharT, _Traits>::extended;
+template <class _CharT, class _Traits>
+ const regex_constants::syntax_option_type basic_regex<_CharT, _Traits>::awk;
+template <class _CharT, class _Traits>
+ const regex_constants::syntax_option_type basic_regex<_CharT, _Traits>::grep;
+template <class _CharT, class _Traits>
+ const regex_constants::syntax_option_type basic_regex<_CharT, _Traits>::egrep;
+
+template <class _CharT, class _Traits>
void
basic_regex<_CharT, _Traits>::swap(basic_regex& __r)
{
diff --git a/contrib/libc++/include/string b/contrib/libc++/include/string
index 5bf42f0..1a70467 100644
--- a/contrib/libc++/include/string
+++ b/contrib/libc++/include/string
@@ -3374,7 +3374,7 @@ basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(value_type __c,
{
const_pointer __p = data();
const_pointer __pe = __p + __sz;
- for (const_pointer __ps = __p + __pos; __p != __pe; ++__ps)
+ for (const_pointer __ps = __p + __pos; __ps != __pe; ++__ps)
if (!traits_type::eq(*__ps, __c))
return static_cast<size_type>(__ps - __p);
}
diff --git a/contrib/libc++/include/type_traits b/contrib/libc++/include/type_traits
index 26c37df..8f1c602 100644
--- a/contrib/libc++/include/type_traits
+++ b/contrib/libc++/include/type_traits
@@ -617,7 +617,28 @@ struct _LIBCPP_VISIBLE is_base_of
#else // __has_feature(is_base_of)
-#error is_base_of not implemented.
+namespace __is_base_of_imp
+{
+template <class _Tp>
+struct _Dst
+{
+ _Dst(const volatile _Tp &);
+};
+template <class _Tp>
+struct _Src
+{
+ operator const volatile _Tp &();
+ template <class _Up> operator const _Dst<_Up> &();
+};
+template <size_t> struct __one { typedef char type; };
+template <class _Bp, class _Dp> typename __one<sizeof(_Dst<_Bp>(declval<_Src<_Dp> >()))>::type __test(int);
+template <class _Bp, class _Dp> __two __test(...);
+}
+
+template <class _Bp, class _Dp>
+struct _LIBCPP_VISIBLE is_base_of
+ : public integral_constant<bool, is_class<_Bp>::value &&
+ sizeof(__is_base_of_imp::__test<_Bp, _Dp>(0)) == 2> {};
#endif // __has_feature(is_base_of)
diff --git a/contrib/libc++/include/vector b/contrib/libc++/include/vector
index 0c28068..876b7e5 100644
--- a/contrib/libc++/include/vector
+++ b/contrib/libc++/include/vector
@@ -1458,7 +1458,8 @@ vector<_Tp, _Allocator>::__push_back_slow_path(_Up& __x)
allocator_type& __a = this->__alloc();
__split_buffer<value_type, allocator_type&> __v(__recommend(size() + 1), size(), __a);
// __v.push_back(_VSTD::forward<_Up>(__x));
- __alloc_traits::construct(__a, _VSTD::__to_raw_pointer(__v.__end_++), _VSTD::forward<_Up>(__x));
+ __alloc_traits::construct(__a, _VSTD::__to_raw_pointer(__v.__end_), _VSTD::forward<_Up>(__x));
+ __v.__end_++;
__swap_out_circular_buffer(__v);
}
@@ -1505,7 +1506,8 @@ vector<_Tp, _Allocator>::__emplace_back_slow_path(_Args&&... __args)
allocator_type& __a = this->__alloc();
__split_buffer<value_type, allocator_type&> __v(__recommend(size() + 1), size(), __a);
// __v.emplace_back(_VSTD::forward<_Args>(__args)...);
- __alloc_traits::construct(__a, _VSTD::__to_raw_pointer(__v.__end_++), _VSTD::forward<_Args>(__args)...);
+ __alloc_traits::construct(__a, _VSTD::__to_raw_pointer(__v.__end_), _VSTD::forward<_Args>(__args)...);
+ __v.__end_++;
__swap_out_circular_buffer(__v);
}
diff --git a/contrib/libc++/src/chrono.cpp b/contrib/libc++/src/chrono.cpp
index 73c83ee..1ce2e28 100644
--- a/contrib/libc++/src/chrono.cpp
+++ b/contrib/libc++/src/chrono.cpp
@@ -24,6 +24,8 @@ namespace chrono
// system_clock
+const bool system_clock::is_steady;
+
system_clock::time_point
system_clock::now() _NOEXCEPT
{
@@ -46,6 +48,8 @@ system_clock::from_time_t(time_t t) _NOEXCEPT
// steady_clock
+const bool steady_clock::is_steady;
+
#if __APPLE__
// mach_absolute_time() * MachInfo.numer / MachInfo.denom is the number of
// nanoseconds since the computer booted up. MachInfo.numer and MachInfo.denom
diff --git a/contrib/libc++/src/debug.cpp b/contrib/libc++/src/debug.cpp
index b8af4dd..f3a0262 100644
--- a/contrib/libc++/src/debug.cpp
+++ b/contrib/libc++/src/debug.cpp
@@ -23,7 +23,7 @@ __get_db()
{
static __libcpp_db db;
return &db;
-};
+}
_LIBCPP_VISIBLE
const __libcpp_db*
diff --git a/contrib/libc++/src/exception.cpp b/contrib/libc++/src/exception.cpp
index 0dbb660..0cd182b 100644
--- a/contrib/libc++/src/exception.cpp
+++ b/contrib/libc++/src/exception.cpp
@@ -33,7 +33,7 @@
#if defined(LIBCXXRT) || defined(_LIBCPPABI_VERSION)
#define HAVE_DEPENDENT_EH_ABI 1
#endif
-#else // __has_include(<cxxabi.h>)
+#elif !defined(__GLIBCXX__) // __has_include(<cxxabi.h>)
static std::terminate_handler __terminate_handler;
static std::unexpected_handler __unexpected_handler;
#endif // __has_include(<cxxabi.h>)
@@ -41,7 +41,7 @@
namespace std
{
-#if !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION)
+#if !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION) && !defined(__GLIBCXX__)
// libcxxrt provides implementations of these functions itself.
unexpected_handler
@@ -99,7 +99,7 @@ terminate() _NOEXCEPT
}
#endif // !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION)
-#ifndef LIBCXXRT
+#if !defined(LIBCXXRT) && !defined(__GLIBCXX__)
bool uncaught_exception() _NOEXCEPT
{
#if __APPLE__ || defined(_LIBCPPABI_VERSION)
@@ -124,7 +124,7 @@ const char* exception::what() const _NOEXCEPT
#endif // _LIBCPPABI_VERSION
#endif //LIBCXXRT
-#ifndef _LIBCPPABI_VERSION
+#if !defined(_LIBCPPABI_VERSION) && !defined(__GLIBCXX__)
bad_exception::~bad_exception() _NOEXCEPT
{
diff --git a/contrib/libc++/src/future.cpp b/contrib/libc++/src/future.cpp
index feb37e4..7d9a5b5 100644
--- a/contrib/libc++/src/future.cpp
+++ b/contrib/libc++/src/future.cpp
@@ -78,8 +78,8 @@ __assoc_sub_state::set_value()
throw future_error(make_error_code(future_errc::promise_already_satisfied));
#endif
__state_ |= __constructed | ready;
- __lk.unlock();
__cv_.notify_all();
+ __lk.unlock();
}
void
diff --git a/contrib/libc++/src/hash.cpp b/contrib/libc++/src/hash.cpp
index 6f30d5a..5587478 100644
--- a/contrib/libc++/src/hash.cpp
+++ b/contrib/libc++/src/hash.cpp
@@ -10,6 +10,14 @@
#include "__hash_table"
#include "algorithm"
#include "stdexcept"
+#include "type_traits"
+
+// Don't silence a non-existent warning if clang doesn't yet have this warning.
+#ifdef __clang__
+#if (__clang_major__ > 3) || ((__clang_major__ == 3) && (__clang_minor__ >= 2))
+#pragma clang diagnostic ignored "-Wtautological-constant-out-of-range-compare"
+#endif
+#endif
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -144,21 +152,23 @@ const unsigned indices[] =
// are fewer potential primes to search, and fewer potential primes to divide
// against.
+template <size_t _Sz = sizeof(size_t)>
inline _LIBCPP_INLINE_VISIBILITY
-void
-__check_for_overflow(size_t N, integral_constant<size_t, 32>)
+typename enable_if<_Sz == 4, void>::type
+__check_for_overflow(size_t N)
{
-#ifndef _LIBCPP_NO_EXCEPTIONS
+#ifndef _LIBCPP_NO_EXCEPTIONS
if (N > 0xFFFFFFFB)
throw overflow_error("__next_prime overflow");
#endif
}
+template <size_t _Sz = sizeof(size_t)>
inline _LIBCPP_INLINE_VISIBILITY
-void
-__check_for_overflow(size_t N, integral_constant<size_t, 64>)
+typename enable_if<_Sz == 8, void>::type
+__check_for_overflow(size_t N)
{
-#ifndef _LIBCPP_NO_EXCEPTIONS
+#ifndef _LIBCPP_NO_EXCEPTIONS
if (N > 0xFFFFFFFFFFFFFFC5ull)
throw overflow_error("__next_prime overflow");
#endif
@@ -174,8 +184,7 @@ __next_prime(size_t n)
return *std::lower_bound(small_primes, small_primes + N, n);
// Else n > largest small_primes
// Check for overflow
- __check_for_overflow(n, integral_constant<size_t,
- sizeof(n) * __CHAR_BIT__>());
+ __check_for_overflow(n);
// Start searching list of potential primes: L * k0 + indices[in]
const size_t M = sizeof(indices) / sizeof(indices[0]);
// Select first potential prime >= n
diff --git a/contrib/libc++/src/locale.cpp b/contrib/libc++/src/locale.cpp
index 542c0d7..53a8a4c 100644
--- a/contrib/libc++/src/locale.cpp
+++ b/contrib/libc++/src/locale.cpp
@@ -81,8 +81,35 @@ make(A0 a0, A1 a1, A2 a2)
return *(T*)&buf;
}
+template <typename T, size_t N>
+inline
+_LIBCPP_CONSTEXPR
+size_t
+countof(const T (&)[N])
+{
+ return N;
+}
+
+template <typename T>
+inline
+_LIBCPP_CONSTEXPR
+size_t
+countof(const T * const begin, const T * const end)
+{
+ return static_cast<size_t>(end - begin);
+}
+
}
+const locale::category locale::none;
+const locale::category locale::collate;
+const locale::category locale::ctype;
+const locale::category locale::monetary;
+const locale::category locale::numeric;
+const locale::category locale::time;
+const locale::category locale::messages;
+const locale::category locale::all;
+
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wpadded"
@@ -197,6 +224,11 @@ locale::__imp::__imp(const string& name, size_t refs)
#endif // _LIBCPP_NO_EXCEPTIONS
}
+// NOTE avoid the `base class should be explicitly initialized in the
+// copy constructor` warning emitted by GCC
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wextra"
+
locale::__imp::__imp(const __imp& other)
: facets_(max<size_t>(N, other.facets_.size())),
name_(other.name_)
@@ -207,6 +239,8 @@ locale::__imp::__imp(const __imp& other)
facets_[i]->__add_shared();
}
+#pragma GCC diagnostic pop
+
locale::__imp::__imp(const __imp& other, const string& name, locale::category c)
: facets_(N),
name_("*")
@@ -691,6 +725,19 @@ collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi)
// template <> class ctype<wchar_t>;
+const ctype_base::mask ctype_base::space;
+const ctype_base::mask ctype_base::print;
+const ctype_base::mask ctype_base::cntrl;
+const ctype_base::mask ctype_base::upper;
+const ctype_base::mask ctype_base::lower;
+const ctype_base::mask ctype_base::alpha;
+const ctype_base::mask ctype_base::digit;
+const ctype_base::mask ctype_base::punct;
+const ctype_base::mask ctype_base::xdigit;
+const ctype_base::mask ctype_base::blank;
+const ctype_base::mask ctype_base::alnum;
+const ctype_base::mask ctype_base::graph;
+
locale::id ctype<wchar_t>::id;
ctype<wchar_t>::~ctype()
@@ -843,7 +890,7 @@ ctype<char>::do_toupper(char_type c) const
return isascii(c) ?
static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c;
#elif defined(__GLIBC__)
- return isascii(c) ? __classic_upper_table()[c] : c;
+ return isascii(c) ? __classic_upper_table()[static_cast<size_t>(c)] : c;
#else
return (isascii(c) && islower_l(c, __cloc())) ? c-'a'+'A' : c;
#endif
@@ -857,7 +904,7 @@ ctype<char>::do_toupper(char_type* low, const char_type* high) const
*low = isascii(*low) ?
static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
#elif defined(__GLIBC__)
- *low = isascii(*low) ? __classic_upper_table()[*low] : *low;
+ *low = isascii(*low) ? __classic_upper_table()[static_cast<size_t>(*low)] : *low;
#else
*low = (isascii(*low) && islower_l(*low, __cloc())) ? *low-'a'+'A' : *low;
#endif
@@ -871,7 +918,7 @@ ctype<char>::do_tolower(char_type c) const
return isascii(c) ?
static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
#elif defined(__GLIBC__)
- return isascii(c) ? __classic_lower_table()[c] : c;
+ return isascii(c) ? __classic_lower_table()[static_cast<size_t>(c)] : c;
#else
return (isascii(c) && isupper_l(c, __cloc())) ? c-'A'+'a' : c;
#endif
@@ -884,7 +931,7 @@ ctype<char>::do_tolower(char_type* low, const char_type* high) const
#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
*low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
#elif defined(__GLIBC__)
- *low = isascii(*low) ? __classic_lower_table()[*low] : *low;
+ *low = isascii(*low) ? __classic_lower_table()[static_cast<size_t>(*low)] : *low;
#else
*low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-'A'+'a' : *low;
#endif
@@ -1207,7 +1254,7 @@ ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
#else
int r = __wctob_l(c, __l);
#endif
- return r != WEOF ? static_cast<char>(r) : dfault;
+ return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
}
const wchar_t*
@@ -1220,7 +1267,7 @@ ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, ch
#else
int r = __wctob_l(*low, __l);
#endif
- *dest = r != WEOF ? static_cast<char>(r) : dfault;
+ *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
}
return low;
}
@@ -2619,7 +2666,6 @@ utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
codecvt_mode mode = codecvt_mode(0))
{
const uint8_t* frm_nxt = frm;
- frm_nxt = frm;
if (mode & consume_header)
{
if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
@@ -2752,7 +2798,6 @@ utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
codecvt_mode mode = codecvt_mode(0))
{
const uint8_t* frm_nxt = frm;
- frm_nxt = frm;
if (mode & consume_header)
{
if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
@@ -2847,7 +2892,6 @@ utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
codecvt_mode mode = codecvt_mode(0))
{
const uint8_t* frm_nxt = frm;
- frm_nxt = frm;
if (mode & consume_header)
{
if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
@@ -4559,6 +4603,7 @@ __time_get::~__time_get()
}
#pragma clang diagnostic ignored "-Wmissing-field-initializers"
+#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
template <>
string
@@ -4578,7 +4623,7 @@ __time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
char f[3] = {0};
f[0] = '%';
f[1] = fmt;
- size_t n = strftime_l(buf, 100, f, &t, __loc_);
+ size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
char* bb = buf;
char* be = buf + n;
string result;
@@ -4724,15 +4769,15 @@ __time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
char f[3] = {0};
f[0] = '%';
f[1] = fmt;
- strftime_l(buf, 100, f, &t, __loc_);
+ strftime_l(buf, countof(buf), f, &t, __loc_);
wchar_t wbuf[100];
wchar_t* wbb = wbuf;
mbstate_t mb = {0};
const char* bb = buf;
#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- size_t j = mbsrtowcs_l( wbb, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
+ size_t j = mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
#else
- size_t j = __mbsrtowcs_l( wbb, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
+ size_t j = __mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
#endif
if (j == size_t(-1))
__throw_runtime_error("locale not supported");
@@ -4870,26 +4915,26 @@ __time_get_storage<char>::init(const ctype<char>& ct)
for (int i = 0; i < 7; ++i)
{
t.tm_wday = i;
- strftime_l(buf, 100, "%A", &t, __loc_);
+ strftime_l(buf, countof(buf), "%A", &t, __loc_);
__weeks_[i] = buf;
- strftime_l(buf, 100, "%a", &t, __loc_);
+ strftime_l(buf, countof(buf), "%a", &t, __loc_);
__weeks_[i+7] = buf;
}
// __months_
for (int i = 0; i < 12; ++i)
{
t.tm_mon = i;
- strftime_l(buf, 100, "%B", &t, __loc_);
+ strftime_l(buf, countof(buf), "%B", &t, __loc_);
__months_[i] = buf;
- strftime_l(buf, 100, "%b", &t, __loc_);
+ strftime_l(buf, countof(buf), "%b", &t, __loc_);
__months_[i+12] = buf;
}
// __am_pm_
t.tm_hour = 1;
- strftime_l(buf, 100, "%p", &t, __loc_);
+ strftime_l(buf, countof(buf), "%p", &t, __loc_);
__am_pm_[0] = buf;
t.tm_hour = 13;
- strftime_l(buf, 100, "%p", &t, __loc_);
+ strftime_l(buf, countof(buf), "%p", &t, __loc_);
__am_pm_[1] = buf;
__c_ = __analyze('c', ct);
__r_ = __analyze('r', ct);
@@ -4903,7 +4948,6 @@ __time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
{
tm t = {0};
char buf[100];
- size_t be;
wchar_t wbuf[100];
wchar_t* wbe;
mbstate_t mb = {0};
@@ -4911,25 +4955,25 @@ __time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
for (int i = 0; i < 7; ++i)
{
t.tm_wday = i;
- be = strftime_l(buf, 100, "%A", &t, __loc_);
+ strftime_l(buf, countof(buf), "%A", &t, __loc_);
mb = mbstate_t();
const char* bb = buf;
#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
+ size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
#else
- size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
+ size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
#endif
if (j == size_t(-1))
__throw_runtime_error("locale not supported");
wbe = wbuf + j;
__weeks_[i].assign(wbuf, wbe);
- be = strftime_l(buf, 100, "%a", &t, __loc_);
+ strftime_l(buf, countof(buf), "%a", &t, __loc_);
mb = mbstate_t();
bb = buf;
#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
+ j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
#else
- j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
+ j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
#endif
if (j == size_t(-1))
__throw_runtime_error("locale not supported");
@@ -4940,25 +4984,25 @@ __time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
for (int i = 0; i < 12; ++i)
{
t.tm_mon = i;
- be = strftime_l(buf, 100, "%B", &t, __loc_);
+ strftime_l(buf, countof(buf), "%B", &t, __loc_);
mb = mbstate_t();
const char* bb = buf;
#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
+ size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
#else
- size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
+ size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
#endif
if (j == size_t(-1))
__throw_runtime_error("locale not supported");
wbe = wbuf + j;
__months_[i].assign(wbuf, wbe);
- be = strftime_l(buf, 100, "%b", &t, __loc_);
+ strftime_l(buf, countof(buf), "%b", &t, __loc_);
mb = mbstate_t();
bb = buf;
#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
+ j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
#else
- j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
+ j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
#endif
if (j == size_t(-1))
__throw_runtime_error("locale not supported");
@@ -4967,26 +5011,26 @@ __time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
}
// __am_pm_
t.tm_hour = 1;
- be = strftime_l(buf, 100, "%p", &t, __loc_);
+ strftime_l(buf, countof(buf), "%p", &t, __loc_);
mb = mbstate_t();
const char* bb = buf;
#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
+ size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
#else
- size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
+ size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
#endif
if (j == size_t(-1))
__throw_runtime_error("locale not supported");
wbe = wbuf + j;
__am_pm_[0].assign(wbuf, wbe);
t.tm_hour = 13;
- be = strftime_l(buf, 100, "%p", &t, __loc_);
+ strftime_l(buf, countof(buf), "%p", &t, __loc_);
mb = mbstate_t();
bb = buf;
#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
+ j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
#else
- j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
+ j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
#endif
if (j == size_t(-1))
__throw_runtime_error("locale not supported");
@@ -5249,7 +5293,7 @@ __time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
char fmt[] = {'%', __fmt, __mod, 0};
if (__mod != 0)
swap(fmt[1], fmt[2]);
- size_t n = strftime_l(__nb, static_cast<size_t>(__ne-__nb), fmt, __tm, __loc_);
+ size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
__ne = __nb + n;
}
@@ -5263,9 +5307,9 @@ __time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
mbstate_t mb = {0};
const char* __nb = __nar;
#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- size_t j = mbsrtowcs_l(__wb, &__nb, 100, &mb, __loc_);
+ size_t j = mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
#else
- size_t j = __mbsrtowcs_l(__wb, &__nb, 100, &mb, __loc_);
+ size_t j = __mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
#endif
if (j == size_t(-1))
__throw_runtime_error("locale not supported");
@@ -5788,9 +5832,9 @@ moneypunct_byname<wchar_t, false>::init(const char* nm)
mbstate_t mb = {0};
const char* bb = lc->currency_symbol;
#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
+ size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
#else
- size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
+ size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
#endif
if (j == size_t(-1))
__throw_runtime_error("locale not supported");
@@ -5807,9 +5851,9 @@ moneypunct_byname<wchar_t, false>::init(const char* nm)
mb = mbstate_t();
bb = lc->positive_sign;
#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
+ j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
#else
- j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
+ j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
#endif
if (j == size_t(-1))
__throw_runtime_error("locale not supported");
@@ -5823,9 +5867,9 @@ moneypunct_byname<wchar_t, false>::init(const char* nm)
mb = mbstate_t();
bb = lc->negative_sign;
#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
+ j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
#else
- j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
+ j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
#endif
if (j == size_t(-1))
__throw_runtime_error("locale not supported");
@@ -5871,9 +5915,9 @@ moneypunct_byname<wchar_t, true>::init(const char* nm)
mbstate_t mb = {0};
const char* bb = lc->int_curr_symbol;
#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
+ size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
#else
- size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
+ size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
#endif
if (j == size_t(-1))
__throw_runtime_error("locale not supported");
@@ -5894,9 +5938,9 @@ moneypunct_byname<wchar_t, true>::init(const char* nm)
mb = mbstate_t();
bb = lc->positive_sign;
#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
+ j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
#else
- j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
+ j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
#endif
if (j == size_t(-1))
__throw_runtime_error("locale not supported");
@@ -5914,9 +5958,9 @@ moneypunct_byname<wchar_t, true>::init(const char* nm)
mb = mbstate_t();
bb = lc->negative_sign;
#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
+ j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
#else
- j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
+ j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
#endif
if (j == size_t(-1))
__throw_runtime_error("locale not supported");
diff --git a/contrib/libc++/src/string.cpp b/contrib/libc++/src/string.cpp
index 750ba28..40723e7 100644
--- a/contrib/libc++/src/string.cpp
+++ b/contrib/libc++/src/string.cpp
@@ -31,17 +31,17 @@ stoi(const string& str, size_t* idx, int base)
{
char* ptr;
const char* const p = str.c_str();
+ typename remove_reference<decltype(errno)>::type errno_save = errno;
+ errno = 0;
long r = strtol(p, &ptr, base);
- if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r)
- ptr = const_cast<char*>(p);
- if (ptr == p)
- {
+ swap(errno, errno_save);
#ifndef _LIBCPP_NO_EXCEPTIONS
- if (r == 0)
- throw invalid_argument("stoi: no conversion");
+ if (errno_save == ERANGE || r < numeric_limits<int>::min() ||
+ numeric_limits<int>::max() < r)
throw out_of_range("stoi: out of range");
+ if (ptr == p)
+ throw invalid_argument("stoi: no conversion");
#endif // _LIBCPP_NO_EXCEPTIONS
- }
if (idx)
*idx = static_cast<size_t>(ptr - p);
return static_cast<int>(r);
@@ -52,17 +52,17 @@ stoi(const wstring& str, size_t* idx, int base)
{
wchar_t* ptr;
const wchar_t* const p = str.c_str();
+ typename remove_reference<decltype(errno)>::type errno_save = errno;
+ errno = 0;
long r = wcstol(p, &ptr, base);
- if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r)
- ptr = const_cast<wchar_t*>(p);
- if (ptr == p)
- {
+ swap(errno, errno_save);
#ifndef _LIBCPP_NO_EXCEPTIONS
- if (r == 0)
- throw invalid_argument("stoi: no conversion");
+ if (errno_save == ERANGE || r < numeric_limits<int>::min() ||
+ numeric_limits<int>::max() < r)
throw out_of_range("stoi: out of range");
+ if (ptr == p)
+ throw invalid_argument("stoi: no conversion");
#endif // _LIBCPP_NO_EXCEPTIONS
- }
if (idx)
*idx = static_cast<size_t>(ptr - p);
return static_cast<int>(r);
@@ -73,15 +73,16 @@ stol(const string& str, size_t* idx, int base)
{
char* ptr;
const char* const p = str.c_str();
+ typename remove_reference<decltype(errno)>::type errno_save = errno;
+ errno = 0;
long r = strtol(p, &ptr, base);
- if (ptr == p)
- {
+ swap(errno, errno_save);
#ifndef _LIBCPP_NO_EXCEPTIONS
- if (r == 0)
- throw invalid_argument("stol: no conversion");
+ if (errno_save == ERANGE)
throw out_of_range("stol: out of range");
+ if (ptr == p)
+ throw invalid_argument("stol: no conversion");
#endif // _LIBCPP_NO_EXCEPTIONS
- }
if (idx)
*idx = static_cast<size_t>(ptr - p);
return r;
@@ -92,15 +93,16 @@ stol(const wstring& str, size_t* idx, int base)
{
wchar_t* ptr;
const wchar_t* const p = str.c_str();
+ typename remove_reference<decltype(errno)>::type errno_save = errno;
+ errno = 0;
long r = wcstol(p, &ptr, base);
- if (ptr == p)
- {
+ swap(errno, errno_save);
#ifndef _LIBCPP_NO_EXCEPTIONS
- if (r == 0)
- throw invalid_argument("stol: no conversion");
+ if (errno_save == ERANGE)
throw out_of_range("stol: out of range");
+ if (ptr == p)
+ throw invalid_argument("stol: no conversion");
#endif // _LIBCPP_NO_EXCEPTIONS
- }
if (idx)
*idx = static_cast<size_t>(ptr - p);
return r;
@@ -111,15 +113,16 @@ stoul(const string& str, size_t* idx, int base)
{
char* ptr;
const char* const p = str.c_str();
+ typename remove_reference<decltype(errno)>::type errno_save = errno;
+ errno = 0;
unsigned long r = strtoul(p, &ptr, base);
- if (ptr == p)
- {
+ swap(errno, errno_save);
#ifndef _LIBCPP_NO_EXCEPTIONS
- if (r == 0)
- throw invalid_argument("stoul: no conversion");
+ if (errno_save == ERANGE)
throw out_of_range("stoul: out of range");
+ if (ptr == p)
+ throw invalid_argument("stoul: no conversion");
#endif // _LIBCPP_NO_EXCEPTIONS
- }
if (idx)
*idx = static_cast<size_t>(ptr - p);
return r;
@@ -130,15 +133,16 @@ stoul(const wstring& str, size_t* idx, int base)
{
wchar_t* ptr;
const wchar_t* const p = str.c_str();
+ typename remove_reference<decltype(errno)>::type errno_save = errno;
+ errno = 0;
unsigned long r = wcstoul(p, &ptr, base);
- if (ptr == p)
- {
+ swap(errno, errno_save);
#ifndef _LIBCPP_NO_EXCEPTIONS
- if (r == 0)
- throw invalid_argument("stoul: no conversion");
+ if (errno_save == ERANGE)
throw out_of_range("stoul: out of range");
+ if (ptr == p)
+ throw invalid_argument("stoul: no conversion");
#endif // _LIBCPP_NO_EXCEPTIONS
- }
if (idx)
*idx = static_cast<size_t>(ptr - p);
return r;
@@ -149,15 +153,16 @@ stoll(const string& str, size_t* idx, int base)
{
char* ptr;
const char* const p = str.c_str();
+ typename remove_reference<decltype(errno)>::type errno_save = errno;
+ errno = 0;
long long r = strtoll(p, &ptr, base);
- if (ptr == p)
- {
+ swap(errno, errno_save);
#ifndef _LIBCPP_NO_EXCEPTIONS
- if (r == 0)
- throw invalid_argument("stoll: no conversion");
+ if (errno_save == ERANGE)
throw out_of_range("stoll: out of range");
+ if (ptr == p)
+ throw invalid_argument("stoll: no conversion");
#endif // _LIBCPP_NO_EXCEPTIONS
- }
if (idx)
*idx = static_cast<size_t>(ptr - p);
return r;
@@ -168,15 +173,16 @@ stoll(const wstring& str, size_t* idx, int base)
{
wchar_t* ptr;
const wchar_t* const p = str.c_str();
+ typename remove_reference<decltype(errno)>::type errno_save = errno;
+ errno = 0;
long long r = wcstoll(p, &ptr, base);
- if (ptr == p)
- {
+ swap(errno, errno_save);
#ifndef _LIBCPP_NO_EXCEPTIONS
- if (r == 0)
- throw invalid_argument("stoll: no conversion");
+ if (errno_save == ERANGE)
throw out_of_range("stoll: out of range");
+ if (ptr == p)
+ throw invalid_argument("stoll: no conversion");
#endif // _LIBCPP_NO_EXCEPTIONS
- }
if (idx)
*idx = static_cast<size_t>(ptr - p);
return r;
@@ -187,15 +193,16 @@ stoull(const string& str, size_t* idx, int base)
{
char* ptr;
const char* const p = str.c_str();
+ typename remove_reference<decltype(errno)>::type errno_save = errno;
+ errno = 0;
unsigned long long r = strtoull(p, &ptr, base);
- if (ptr == p)
- {
+ swap(errno, errno_save);
#ifndef _LIBCPP_NO_EXCEPTIONS
- if (r == 0)
- throw invalid_argument("stoull: no conversion");
+ if (errno_save == ERANGE)
throw out_of_range("stoull: out of range");
+ if (ptr == p)
+ throw invalid_argument("stoull: no conversion");
#endif // _LIBCPP_NO_EXCEPTIONS
- }
if (idx)
*idx = static_cast<size_t>(ptr - p);
return r;
@@ -206,15 +213,16 @@ stoull(const wstring& str, size_t* idx, int base)
{
wchar_t* ptr;
const wchar_t* const p = str.c_str();
+ typename remove_reference<decltype(errno)>::type errno_save = errno;
+ errno = 0;
unsigned long long r = wcstoull(p, &ptr, base);
- if (ptr == p)
- {
+ swap(errno, errno_save);
#ifndef _LIBCPP_NO_EXCEPTIONS
- if (r == 0)
- throw invalid_argument("stoull: no conversion");
+ if (errno_save == ERANGE)
throw out_of_range("stoull: out of range");
+ if (ptr == p)
+ throw invalid_argument("stoull: no conversion");
#endif // _LIBCPP_NO_EXCEPTIONS
- }
if (idx)
*idx = static_cast<size_t>(ptr - p);
return r;
@@ -225,9 +233,9 @@ stof(const string& str, size_t* idx)
{
char* ptr;
const char* const p = str.c_str();
- int errno_save = errno;
+ typename remove_reference<decltype(errno)>::type errno_save = errno;
errno = 0;
- double r = strtod(p, &ptr);
+ float r = strtof(p, &ptr);
swap(errno, errno_save);
#ifndef _LIBCPP_NO_EXCEPTIONS
if (errno_save == ERANGE)
@@ -237,7 +245,7 @@ stof(const string& str, size_t* idx)
#endif // _LIBCPP_NO_EXCEPTIONS
if (idx)
*idx = static_cast<size_t>(ptr - p);
- return static_cast<float>(r);
+ return r;
}
float
@@ -245,9 +253,9 @@ stof(const wstring& str, size_t* idx)
{
wchar_t* ptr;
const wchar_t* const p = str.c_str();
- int errno_save = errno;
+ typename remove_reference<decltype(errno)>::type errno_save = errno;
errno = 0;
- double r = wcstod(p, &ptr);
+ float r = wcstof(p, &ptr);
swap(errno, errno_save);
#ifndef _LIBCPP_NO_EXCEPTIONS
if (errno_save == ERANGE)
@@ -257,7 +265,7 @@ stof(const wstring& str, size_t* idx)
#endif // _LIBCPP_NO_EXCEPTIONS
if (idx)
*idx = static_cast<size_t>(ptr - p);
- return static_cast<float>(r);
+ return r;
}
double
@@ -265,7 +273,7 @@ stod(const string& str, size_t* idx)
{
char* ptr;
const char* const p = str.c_str();
- int errno_save = errno;
+ typename remove_reference<decltype(errno)>::type errno_save = errno;
errno = 0;
double r = strtod(p, &ptr);
swap(errno, errno_save);
@@ -285,7 +293,7 @@ stod(const wstring& str, size_t* idx)
{
wchar_t* ptr;
const wchar_t* const p = str.c_str();
- int errno_save = errno;
+ typename remove_reference<decltype(errno)>::type errno_save = errno;
errno = 0;
double r = wcstod(p, &ptr);
swap(errno, errno_save);
@@ -305,7 +313,7 @@ stold(const string& str, size_t* idx)
{
char* ptr;
const char* const p = str.c_str();
- int errno_save = errno;
+ typename remove_reference<decltype(errno)>::type errno_save = errno;
errno = 0;
long double r = strtold(p, &ptr);
swap(errno, errno_save);
@@ -325,7 +333,7 @@ stold(const wstring& str, size_t* idx)
{
wchar_t* ptr;
const wchar_t* const p = str.c_str();
- int errno_save = errno;
+ typename remove_reference<decltype(errno)>::type errno_save = errno;
errno = 0;
long double r = wcstold(p, &ptr);
swap(errno, errno_save);
diff --git a/contrib/libc++/src/thread.cpp b/contrib/libc++/src/thread.cpp
index 8747adf..b2bd07e 100644
--- a/contrib/libc++/src/thread.cpp
+++ b/contrib/libc++/src/thread.cpp
@@ -67,8 +67,10 @@ thread::hardware_concurrency() _NOEXCEPT
return n;
#elif defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L) && defined(_SC_NPROCESSORS_ONLN)
long result = sysconf(_SC_NPROCESSORS_ONLN);
- if (result < 0 || result > UINT_MAX)
- result = 0;
+ // sysconf returns -1 if the name is invalid, the option does not exist or
+ // does not have a definite limit.
+ if (result == -1)
+ return 0;
return result;
#else // defined(CTL_HW) && defined(HW_NCPU)
// TODO: grovel through /proc or check cpuid on x86 and similar
diff --git a/lib/libc/sys/ptrace.2 b/lib/libc/sys/ptrace.2
index 9dda8ee..90c4544 100644
--- a/lib/libc/sys/ptrace.2
+++ b/lib/libc/sys/ptrace.2
@@ -2,7 +2,7 @@
.\" $NetBSD: ptrace.2,v 1.2 1995/02/27 12:35:37 cgd Exp $
.\"
.\" This file is in the public domain.
-.Dd February 19, 2012
+.Dd February 7, 2013
.Dt PTRACE 2
.Os
.Sh NAME
@@ -100,6 +100,16 @@ or any of the routines built on it
it will stop before executing the first instruction of the new image.
Also, any setuid or setgid bits on the executable being executed will
be ignored.
+If the child was created by
+.Xr vfork 2
+system call or
+.Xr rfork(2)
+call with the
+.Dv RFMEM
+flag specified, the debugging events are reported to the parent
+only after the
+.Xr execve 2
+is executed.
.It Dv PT_READ_I , Dv PT_READ_D
These requests read a single
.Vt int
diff --git a/libexec/rtld-elf/powerpc64/reloc.c b/libexec/rtld-elf/powerpc64/reloc.c
index b13500f..fb5325f 100644
--- a/libexec/rtld-elf/powerpc64/reloc.c
+++ b/libexec/rtld-elf/powerpc64/reloc.c
@@ -486,8 +486,7 @@ init_pltgot(Obj_Entry *obj)
void
allocate_initial_tls(Obj_Entry *list)
{
- register Elf_Addr **tp __asm__("r13");
- Elf_Addr **_tp;
+ Elf_Addr **tp;
/*
* Fix the size of the static TLS block by using the maximum
@@ -497,22 +496,19 @@ allocate_initial_tls(Obj_Entry *list)
tls_static_space = tls_last_offset + tls_last_size + RTLD_STATIC_TLS_EXTRA;
- _tp = (Elf_Addr **) ((char *)allocate_tls(list, NULL, TLS_TCB_SIZE, 16)
+ tp = (Elf_Addr **) ((char *)allocate_tls(list, NULL, TLS_TCB_SIZE, 16)
+ TLS_TP_OFFSET + TLS_TCB_SIZE);
- /*
- * XXX gcc seems to ignore 'tp = _tp;'
- */
-
- __asm __volatile("mr %0,%1" : "=r"(tp) : "r"(_tp));
+ __asm __volatile("mr 13,%0" :: "r"(tp));
}
void*
__tls_get_addr(tls_index* ti)
{
- register Elf_Addr **tp __asm__("r13");
+ Elf_Addr **tp;
char *p;
+ __asm __volatile("mr %0,13" : "=r"(tp));
p = tls_get_addr_common((Elf_Addr**)((Elf_Addr)tp - TLS_TP_OFFSET
- TLS_TCB_SIZE), ti->ti_module, ti->ti_offset);
diff --git a/sbin/ifconfig/ifieee80211.c b/sbin/ifconfig/ifieee80211.c
index c2b7678..d0b4917 100644
--- a/sbin/ifconfig/ifieee80211.c
+++ b/sbin/ifconfig/ifieee80211.c
@@ -4025,7 +4025,9 @@ list_mesh(int s)
(rt->imr_flags & IEEE80211_MESHRT_FLAGS_VALID) ?
'V' : '!',
(rt->imr_flags & IEEE80211_MESHRT_FLAGS_PROXY) ?
- 'P' : ' ');
+ 'P' :
+ (rt->imr_flags & IEEE80211_MESHRT_FLAGS_GATE) ?
+ 'G' :' ');
}
}
diff --git a/share/man/man5/group.5 b/share/man/man5/group.5
index 4aa6aff..4a366f6 100644
--- a/share/man/man5/group.5
+++ b/share/man/man5/group.5
@@ -32,7 +32,7 @@
.\" From: @(#)group.5 8.3 (Berkeley) 4/19/94
.\" $FreeBSD$
.\"
-.Dd September 29, 1994
+.Dd February 8, 2013
.Dt GROUP 5
.Os
.Sh NAME
@@ -139,6 +139,7 @@ may still have this limit.
.It Pa /etc/group
.El
.Sh SEE ALSO
+.Xr newgrp 1 ,
.Xr passwd 1 ,
.Xr setgroups 2 ,
.Xr crypt 3 ,
@@ -156,9 +157,14 @@ file format appeared in
.At v6 .
Support for comments first appeared in
.Fx 3.0 .
-.Sh BUGS
+.Sh IMPLEMENTATION NOTES
The
.Xr passwd 1
command does not change the
.Nm
passwords.
+The
+.Xr pw 8
+utility's
+.Cm groupmod
+command should be used instead.
diff --git a/share/man/man9/timeout.9 b/share/man/man9/timeout.9
index 543d198..c671467 100644
--- a/share/man/man9/timeout.9
+++ b/share/man/man9/timeout.9
@@ -62,7 +62,7 @@ typedef void timeout_t (void *);
.Ft void
.Fn callout_handle_init "struct callout_handle *handle"
.Bd -literal
-struct callout_handle handle = CALLOUT_HANDLE_INITIALIZER(&handle)
+struct callout_handle handle = CALLOUT_HANDLE_INITIALIZER(&handle);
.Ed
.Ft void
.Fn untimeout "timeout_t *func" "void *arg" "struct callout_handle handle"
diff --git a/sys/boot/usb/Makefile.test b/sys/boot/usb/Makefile.test
index a366d36..b7139e7 100644
--- a/sys/boot/usb/Makefile.test
+++ b/sys/boot/usb/Makefile.test
@@ -53,9 +53,9 @@ SRCS+= bsd_usbloader_test.c
LDADD+= libusbboot.a
DPADD+= libusbboot.a
-all: libusbboot.a
-
.include <bsd.prog.mk>
+${PROG}: libusbboot.a
+
libusbboot.a:
make -f Makefile
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_vfsops.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_vfsops.h
index 63cfb00..3559f0d 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_vfsops.h
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_vfsops.h
@@ -110,7 +110,7 @@ typedef struct zfid_short {
} zfid_short_t;
/*
- * Filesystems under .zfs/snapshot have a total file ID size of 22 bytes
+ * Filesystems under .zfs/snapshot have a total file ID size of 22[*] bytes
* (including the length field). This makes files under .zfs/snapshot
* accessible by NFSv3 and NFSv4, but not NFSv2.
*
@@ -120,10 +120,13 @@ typedef struct zfid_short {
* 6 bytes object number (48 bits)
* 4 bytes generation number (32 bits)
* 6 bytes objset id (48 bits)
- * 4 bytes currently just zero (32 bits)
+ * 4 bytes[**] currently just zero (32 bits)
*
* We reserve only 48 bits for the object number and objset id, as these are
* the limits currently defined and imposed by the DMU.
+ *
+ * [*] 20 bytes on FreeBSD to fit into the size of struct fid.
+ * [**] 2 bytes on FreeBSD for the above reason.
*/
typedef struct zfid_long {
zfid_short_t z_fid;
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
index 7f3f7a1..456e5aa 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
@@ -2009,7 +2009,8 @@ zfs_vget(vfs_t *vfsp, ino_t ino, int flags, vnode_t **vpp)
* .zfs/snapshot/ directories, that's why we return EOPNOTSUPP.
* This will make NFS to switch to LOOKUP instead of using VGET.
*/
- if (ino == ZFSCTL_INO_ROOT || ino == ZFSCTL_INO_SNAPDIR)
+ if (ino == ZFSCTL_INO_ROOT || ino == ZFSCTL_INO_SNAPDIR ||
+ (zfsvfs->z_shares_dir != 0 && ino == zfsvfs->z_shares_dir))
return (EOPNOTSUPP);
ZFS_ENTER(zfsvfs);
@@ -2101,14 +2102,22 @@ zfs_fhtovp(vfs_t *vfsp, fid_t *fidp, int flags, vnode_t **vpp)
return (EINVAL);
}
- /* A zero fid_gen means we are in the .zfs control directories */
- if (fid_gen == 0 &&
- (object == ZFSCTL_INO_ROOT || object == ZFSCTL_INO_SNAPDIR)) {
+ /*
+ * A zero fid_gen means we are in .zfs or the .zfs/snapshot
+ * directory tree. If the object == zfsvfs->z_shares_dir, then
+ * we are in the .zfs/shares directory tree.
+ */
+ if ((fid_gen == 0 &&
+ (object == ZFSCTL_INO_ROOT || object == ZFSCTL_INO_SNAPDIR)) ||
+ (zfsvfs->z_shares_dir != 0 && object == zfsvfs->z_shares_dir)) {
*vpp = zfsvfs->z_ctldir;
ASSERT(*vpp != NULL);
if (object == ZFSCTL_INO_SNAPDIR) {
VERIFY(zfsctl_root_lookup(*vpp, "snapshot", vpp, NULL,
0, NULL, NULL, NULL, NULL, NULL) == 0);
+ } else if (object == zfsvfs->z_shares_dir) {
+ VERIFY(zfsctl_root_lookup(*vpp, "shares", vpp, NULL,
+ 0, NULL, NULL, NULL, NULL, NULL) == 0);
} else {
VN_HOLD(*vpp);
}
diff --git a/sys/cddl/dev/dtrace/dtrace_ioctl.c b/sys/cddl/dev/dtrace/dtrace_ioctl.c
index fbc891d..6a01e13 100644
--- a/sys/cddl/dev/dtrace/dtrace_ioctl.c
+++ b/sys/cddl/dev/dtrace/dtrace_ioctl.c
@@ -215,7 +215,7 @@ dtrace_ioctl(struct cdev *dev, u_long cmd, caddr_t addr,
"DTRACEIOC_AGGSNAP":"DTRACEIOC_BUFSNAP",
curcpu, desc.dtbd_cpu);
- if (desc.dtbd_cpu < 0 || desc.dtbd_cpu >= NCPU)
+ if (desc.dtbd_cpu >= NCPU)
return (ENOENT);
if (pcpu_find(desc.dtbd_cpu) == NULL)
return (ENOENT);
diff --git a/sys/conf/NOTES b/sys/conf/NOTES
index ff245ed..5d26093 100644
--- a/sys/conf/NOTES
+++ b/sys/conf/NOTES
@@ -462,7 +462,7 @@ options KTRACE_REQUEST_POOL=101
#
options KTR
options KTR_BOOT_ENTRIES=1024
-options KTR_ENTRIES=(128 * 1024)
+options KTR_ENTRIES=(128*1024)
options KTR_COMPILE=(KTR_INTR|KTR_PROC)
options KTR_MASK=KTR_INTR
options KTR_CPUMASK=0x3
diff --git a/sys/dev/ath/if_ath_tx_ht.c b/sys/dev/ath/if_ath_tx_ht.c
index e8319cd..60a1863 100644
--- a/sys/dev/ath/if_ath_tx_ht.c
+++ b/sys/dev/ath/if_ath_tx_ht.c
@@ -688,11 +688,6 @@ ath_tx_form_aggr(struct ath_softc *sc, struct ath_node *an,
bf->bf_next = NULL;
/*
- * Don't unlock the tid lock until we're sure we are going
- * to queue this frame.
- */
-
- /*
* If the frame doesn't have a sequence number that we're
* tracking in the BAW (eg NULL QOS data frame), we can't
* aggregate it. Stop the aggregation process; the sender
@@ -749,11 +744,13 @@ ath_tx_form_aggr(struct ath_softc *sc, struct ath_node *an,
* that differs from the first frame, override the
* subsequent frame with this config.
*/
- bf->bf_state.bfs_txflags &=
- ~ (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA);
- bf->bf_state.bfs_txflags |=
- bf_first->bf_state.bfs_txflags &
- (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA);
+ if (bf != bf_first) {
+ bf->bf_state.bfs_txflags &=
+ ~ (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA);
+ bf->bf_state.bfs_txflags |=
+ bf_first->bf_state.bfs_txflags &
+ (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA);
+ }
/*
* If the packet has a sequence number, do not
diff --git a/sys/dev/bxe/if_bxe.c b/sys/dev/bxe/if_bxe.c
index 52d2c1b..9566b27 100644
--- a/sys/dev/bxe/if_bxe.c
+++ b/sys/dev/bxe/if_bxe.c
@@ -9506,24 +9506,15 @@ bxe_tx_mq_start_locked(struct ifnet *ifp,
BXE_FP_LOCK_ASSERT(fp);
- if (m == NULL) {
- /* No new work, check for pending frames. */
- next = drbr_dequeue(ifp, fp->br);
- } else if (drbr_needs_enqueue(ifp, fp->br)) {
- /* Both new and pending work, maintain packet order. */
+ if (m != NULL) {
rc = drbr_enqueue(ifp, fp->br, m);
if (rc != 0) {
fp->tx_soft_errors++;
goto bxe_tx_mq_start_locked_exit;
}
- next = drbr_dequeue(ifp, fp->br);
- } else
- /* New work only, nothing pending. */
- next = m;
-
+ }
/* Keep adding entries while there are frames to send. */
- while (next != NULL) {
-
+ while ((next = drbr_peek(ifp, fp->br)) != NULL) {
/* The transmit mbuf now belongs to us, keep track of it. */
fp->tx_mbuf_alloc++;
@@ -9537,23 +9528,22 @@ bxe_tx_mq_start_locked(struct ifnet *ifp,
if (__predict_false(rc != 0)) {
fp->tx_encap_failures++;
/* Very Bad Frames(tm) may have been dropped. */
- if (next != NULL) {
+ if (next == NULL) {
+ drbr_advance(ifp, fp->br);
+ } else {
+ drbr_putback(ifp, fp->br, next);
/*
* Mark the TX queue as full and save
* the frame.
*/
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
fp->tx_frame_deferred++;
-
- /* This may reorder frame. */
- rc = drbr_enqueue(ifp, fp->br, next);
fp->tx_mbuf_alloc--;
}
-
/* Stop looking for more work. */
break;
}
-
+ drbr_advance(ifp, fp->br);
/* The transmit frame was enqueued successfully. */
tx_count++;
@@ -9574,8 +9564,6 @@ bxe_tx_mq_start_locked(struct ifnet *ifp,
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
break;
}
-
- next = drbr_dequeue(ifp, fp->br);
}
/* No TX packets were dequeued. */
diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c
index 3344697..a431266 100644
--- a/sys/dev/e1000/if_em.c
+++ b/sys/dev/e1000/if_em.c
@@ -905,22 +905,24 @@ em_mq_start_locked(struct ifnet *ifp, struct tx_ring *txr, struct mbuf *m)
}
enq = 0;
- if (m == NULL) {
- next = drbr_dequeue(ifp, txr->br);
- } else if (drbr_needs_enqueue(ifp, txr->br)) {
- if ((err = drbr_enqueue(ifp, txr->br, m)) != 0)
+ if (m != NULL) {
+ err = drbr_enqueue(ifp, txr->br, m);
+ if (err) {
return (err);
- next = drbr_dequeue(ifp, txr->br);
- } else
- next = m;
+ }
+ }
/* Process the queue */
- while (next != NULL) {
+ while ((next = drbr_peek(ifp, txr->br)) != NULL) {
if ((err = em_xmit(txr, &next)) != 0) {
- if (next != NULL)
- err = drbr_enqueue(ifp, txr->br, next);
- break;
+ if (next == NULL) {
+ drbr_advance(ifp, txr->br);
+ } else {
+ drbr_putback(ifp, txr->br, next);
+ }
+ break;
}
+ drbr_advance(ifp, txr->br);
enq++;
ifp->if_obytes += next->m_pkthdr.len;
if (next->m_flags & M_MCAST)
@@ -928,7 +930,6 @@ em_mq_start_locked(struct ifnet *ifp, struct tx_ring *txr, struct mbuf *m)
ETHER_BPF_MTAP(ifp, next);
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
break;
- next = drbr_dequeue(ifp, txr->br);
}
if (enq > 0) {
diff --git a/sys/dev/e1000/if_igb.c b/sys/dev/e1000/if_igb.c
index 2921a91..8c6b429 100644
--- a/sys/dev/e1000/if_igb.c
+++ b/sys/dev/e1000/if_igb.c
@@ -350,6 +350,16 @@ TUNABLE_INT("hw.igb.max_interrupt_rate", &igb_max_interrupt_rate);
SYSCTL_INT(_hw_igb, OID_AUTO, max_interrupt_rate, CTLFLAG_RDTUN,
&igb_max_interrupt_rate, 0, "Maximum interrupts per second");
+#if __FreeBSD_version >= 800000
+/*
+** Tuneable number of buffers in the buf-ring (drbr_xxx)
+*/
+static int igb_buf_ring_size = IGB_BR_SIZE;
+TUNABLE_INT("hw.igb.buf_ring_size", &igb_buf_ring_size);
+SYSCTL_INT(_hw_igb, OID_AUTO, buf_ring_size, CTLFLAG_RDTUN,
+ &igb_buf_ring_size, 0, "Size of the bufring");
+#endif
+
/*
** Header split causes the packet header to
** be dma'd to a seperate mbuf from the payload.
@@ -965,12 +975,13 @@ igb_mq_start(struct ifnet *ifp, struct mbuf *m)
** out-of-order delivery, but
** settle for it if that fails
*/
- if (m)
+ if (m != NULL)
drbr_enqueue(ifp, txr->br, m);
err = igb_mq_start_locked(ifp, txr);
IGB_TX_UNLOCK(txr);
} else {
- err = drbr_enqueue(ifp, txr->br, m);
+ if (m != NULL)
+ err = drbr_enqueue(ifp, txr->br, m);
taskqueue_enqueue(que->tq, &txr->txq_task);
}
@@ -994,12 +1005,22 @@ igb_mq_start_locked(struct ifnet *ifp, struct tx_ring *txr)
enq = 0;
/* Process the queue */
- while ((next = drbr_dequeue(ifp, txr->br)) != NULL) {
+ while ((next = drbr_peek(ifp, txr->br)) != NULL) {
if ((err = igb_xmit(txr, &next)) != 0) {
- if (next != NULL)
- err = drbr_enqueue(ifp, txr->br, next);
+ if (next == NULL) {
+ /* It was freed, move forward */
+ drbr_advance(ifp, txr->br);
+ } else {
+ /*
+ * Still have one left, it may not be
+ * the same since the transmit function
+ * may have changed it.
+ */
+ drbr_putback(ifp, txr->br, next);
+ }
break;
}
+ drbr_advance(ifp, txr->br);
enq++;
ifp->if_obytes += next->m_pkthdr.len;
if (next->m_flags & M_MCAST)
@@ -3301,7 +3322,7 @@ igb_allocate_queues(struct adapter *adapter)
}
#if __FreeBSD_version >= 800000
/* Allocate a buf ring */
- txr->br = buf_ring_alloc(IGB_BR_SIZE, M_DEVBUF,
+ txr->br = buf_ring_alloc(igb_buf_ring_size, M_DEVBUF,
M_WAITOK, &txr->tx_mtx);
#endif
}
diff --git a/sys/dev/ixgbe/ixgbe.c b/sys/dev/ixgbe/ixgbe.c
index cfcc342..0b77437 100644
--- a/sys/dev/ixgbe/ixgbe.c
+++ b/sys/dev/ixgbe/ixgbe.c
@@ -832,22 +832,24 @@ ixgbe_mq_start_locked(struct ifnet *ifp, struct tx_ring *txr, struct mbuf *m)
}
enqueued = 0;
- if (m == NULL) {
- next = drbr_dequeue(ifp, txr->br);
- } else if (drbr_needs_enqueue(ifp, txr->br)) {
- if ((err = drbr_enqueue(ifp, txr->br, m)) != 0)
+ if (m != NULL) {
+ err = drbr_enqueue(ifp, txr->br, m);
+ if (err) {
return (err);
- next = drbr_dequeue(ifp, txr->br);
- } else
- next = m;
+ }
+ }
/* Process the queue */
- while (next != NULL) {
+ while ((next = drbr_peek(ifp, txr->br)) != NULL) {
if ((err = ixgbe_xmit(txr, &next)) != 0) {
- if (next != NULL)
- err = drbr_enqueue(ifp, txr->br, next);
+ if (next == NULL) {
+ drbr_advance(ifp, txr->br);
+ } else {
+ drbr_putback(ifp, txr->br, next);
+ }
break;
}
+ drbr_advance(ifp, txr->br);
enqueued++;
/* Send a copy of the frame to the BPF listener */
ETHER_BPF_MTAP(ifp, next);
@@ -855,7 +857,6 @@ ixgbe_mq_start_locked(struct ifnet *ifp, struct tx_ring *txr, struct mbuf *m)
break;
if (txr->tx_avail < IXGBE_TX_OP_THRESHOLD)
ixgbe_txeof(txr);
- next = drbr_dequeue(ifp, txr->br);
}
if (enqueued > 0) {
diff --git a/sys/dev/ixgbe/ixv.c b/sys/dev/ixgbe/ixv.c
index ef5f753..b3a3d64 100644
--- a/sys/dev/ixgbe/ixv.c
+++ b/sys/dev/ixgbe/ixv.c
@@ -620,22 +620,23 @@ ixv_mq_start_locked(struct ifnet *ifp, struct tx_ring *txr, struct mbuf *m)
ixv_txeof(txr);
enqueued = 0;
- if (m == NULL) {
- next = drbr_dequeue(ifp, txr->br);
- } else if (drbr_needs_enqueue(ifp, txr->br)) {
- if ((err = drbr_enqueue(ifp, txr->br, m)) != 0)
+ if (m != NULL) {
+ err = drbr_enqueue(ifp, txr->br, m);
+ if (err) {
return (err);
- next = drbr_dequeue(ifp, txr->br);
- } else
- next = m;
-
+ }
+ }
/* Process the queue */
- while (next != NULL) {
+ while ((next = drbr_peek(ifp, txr->br)) != NULL) {
if ((err = ixv_xmit(txr, &next)) != 0) {
- if (next != NULL)
- err = drbr_enqueue(ifp, txr->br, next);
+ if (next == NULL) {
+ drbr_advance(ifp, txr->br);
+ } else {
+ drbr_putback(ifp, txr->br, next);
+ }
break;
}
+ drbr_advance(ifp, txr->br);
enqueued++;
ifp->if_obytes += next->m_pkthdr.len;
if (next->m_flags & M_MCAST)
@@ -648,7 +649,6 @@ ixv_mq_start_locked(struct ifnet *ifp, struct tx_ring *txr, struct mbuf *m)
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
break;
}
- next = drbr_dequeue(ifp, txr->br);
}
if (enqueued > 0) {
diff --git a/sys/dev/oce/oce_if.c b/sys/dev/oce/oce_if.c
index cba57bf..2b4c181 100644
--- a/sys/dev/oce/oce_if.c
+++ b/sys/dev/oce/oce_if.c
@@ -1166,29 +1166,27 @@ oce_multiq_transmit(struct ifnet *ifp, struct mbuf *m, struct oce_wq *wq)
return status;
}
- if (m == NULL)
- next = drbr_dequeue(ifp, br);
- else if (drbr_needs_enqueue(ifp, br)) {
+ if (m != NULL) {
if ((status = drbr_enqueue(ifp, br, m)) != 0)
return status;
- next = drbr_dequeue(ifp, br);
- } else
- next = m;
-
- while (next != NULL) {
+ }
+ while ((next = drbr_peek(ifp, br)) != NULL) {
if (oce_tx(sc, &next, queue_index)) {
- if (next != NULL) {
+ if (next == NULL) {
+ drbr_advance(ifp, br);
+ } else {
+ drbr_putback(ifp, br, next);
wq->tx_stats.tx_stops ++;
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
status = drbr_enqueue(ifp, br, next);
}
break;
}
+ drbr_advance(ifp, br);
ifp->if_obytes += next->m_pkthdr.len;
if (next->m_flags & M_MCAST)
ifp->if_omcasts++;
ETHER_BPF_MTAP(ifp, next);
- next = drbr_dequeue(ifp, br);
}
return status;
diff --git a/sys/dev/usb/wlan/if_uath.c b/sys/dev/usb/wlan/if_uath.c
index 0ac57af..938e52e 100644
--- a/sys/dev/usb/wlan/if_uath.c
+++ b/sys/dev/usb/wlan/if_uath.c
@@ -358,22 +358,12 @@ uath_attach(device_t dev)
callout_init(&sc->stat_ch, 0);
callout_init_mtx(&sc->watchdog_ch, &sc->sc_mtx, 0);
- /*
- * Allocate xfers for firmware commands.
- */
- error = uath_alloc_cmd_list(sc, sc->sc_cmd);
- if (error != 0) {
- device_printf(sc->sc_dev,
- "could not allocate Tx command list\n");
- goto fail;
- }
-
error = usbd_transfer_setup(uaa->device, &iface_index, sc->sc_xfer,
uath_usbconfig, UATH_N_XFERS, sc, &sc->sc_mtx);
if (error) {
device_printf(dev, "could not allocate USB transfers, "
"err=%s\n", usbd_errstr(error));
- goto fail1;
+ goto fail;
}
sc->sc_cmd_dma_buf =
@@ -382,6 +372,16 @@ uath_attach(device_t dev)
usbd_xfer_get_frame_buffer(sc->sc_xfer[UATH_BULK_TX], 0);
/*
+ * Setup buffers for firmware commands.
+ */
+ error = uath_alloc_cmd_list(sc, sc->sc_cmd);
+ if (error != 0) {
+ device_printf(sc->sc_dev,
+ "could not allocate Tx command list\n");
+ goto fail1;
+ }
+
+ /*
* We're now ready to send+receive firmware commands.
*/
UATH_LOCK(sc);
@@ -492,8 +492,8 @@ uath_attach(device_t dev)
fail4: if_free(ifp);
fail3: UATH_UNLOCK(sc);
-fail2: usbd_transfer_unsetup(sc->sc_xfer, UATH_N_XFERS);
-fail1: uath_free_cmd_list(sc, sc->sc_cmd);
+fail2: uath_free_cmd_list(sc, sc->sc_cmd);
+fail1: usbd_transfer_unsetup(sc->sc_xfer, UATH_N_XFERS);
fail:
return (error);
}
@@ -2436,11 +2436,8 @@ uath_intr_tx_callback(struct usb_xfer *xfer, usb_error_t error)
UATH_ASSERT_LOCKED(sc);
- switch (USB_GET_STATE(xfer)) {
- case USB_ST_TRANSFERRED:
- cmd = STAILQ_FIRST(&sc->sc_cmd_active);
- if (cmd == NULL)
- goto setup;
+ cmd = STAILQ_FIRST(&sc->sc_cmd_active);
+ if (cmd != NULL && USB_GET_STATE(xfer) != USB_ST_SETUP) {
STAILQ_REMOVE_HEAD(&sc->sc_cmd_active, next);
UATH_STAT_DEC(sc, st_cmd_active);
STAILQ_INSERT_TAIL((cmd->flags & UATH_CMD_FLAG_READ) ?
@@ -2449,7 +2446,10 @@ uath_intr_tx_callback(struct usb_xfer *xfer, usb_error_t error)
UATH_STAT_INC(sc, st_cmd_waiting);
else
UATH_STAT_INC(sc, st_cmd_inactive);
- /* FALLTHROUGH */
+ }
+
+ switch (USB_GET_STATE(xfer)) {
+ case USB_ST_TRANSFERRED:
case USB_ST_SETUP:
setup:
cmd = STAILQ_FIRST(&sc->sc_cmd_pending);
diff --git a/sys/dev/usb/wlan/if_upgt.c b/sys/dev/usb/wlan/if_upgt.c
index c625926..6b49df1 100644
--- a/sys/dev/usb/wlan/if_upgt.c
+++ b/sys/dev/usb/wlan/if_upgt.c
@@ -259,20 +259,12 @@ upgt_attach(device_t dev)
callout_init(&sc->sc_led_ch, 0);
callout_init(&sc->sc_watchdog_ch, 0);
- /* Allocate TX and RX xfers. */
- error = upgt_alloc_tx(sc);
- if (error)
- goto fail1;
- error = upgt_alloc_rx(sc);
- if (error)
- goto fail2;
-
error = usbd_transfer_setup(uaa->device, &iface_index, sc->sc_xfer,
upgt_config, UPGT_N_XFERS, sc, &sc->sc_mtx);
if (error) {
device_printf(dev, "could not allocate USB transfers, "
"err=%s\n", usbd_errstr(error));
- goto fail3;
+ goto fail1;
}
sc->sc_rx_dma_buf = usbd_xfer_get_frame_buffer(
@@ -280,6 +272,14 @@ upgt_attach(device_t dev)
sc->sc_tx_dma_buf = usbd_xfer_get_frame_buffer(
sc->sc_xfer[UPGT_BULK_TX], 0);
+ /* Setup TX and RX buffers */
+ error = upgt_alloc_tx(sc);
+ if (error)
+ goto fail2;
+ error = upgt_alloc_rx(sc);
+ if (error)
+ goto fail3;
+
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
if (ifp == NULL) {
device_printf(dev, "can not if_alloc()\n");
@@ -382,9 +382,9 @@ upgt_attach(device_t dev)
return (0);
fail5: if_free(ifp);
-fail4: usbd_transfer_unsetup(sc->sc_xfer, UPGT_N_XFERS);
-fail3: upgt_free_rx(sc);
-fail2: upgt_free_tx(sc);
+fail4: upgt_free_rx(sc);
+fail3: upgt_free_tx(sc);
+fail2: usbd_transfer_unsetup(sc->sc_xfer, UPGT_N_XFERS);
fail1: mtx_destroy(&sc->sc_mtx);
return (error);
diff --git a/sys/fs/ext2fs/ext2_vfsops.c b/sys/fs/ext2fs/ext2_vfsops.c
index 136f01c..cdb41ba 100644
--- a/sys/fs/ext2fs/ext2_vfsops.c
+++ b/sys/fs/ext2fs/ext2_vfsops.c
@@ -320,8 +320,8 @@ compute_sb_data(struct vnode *devvp, struct ext2fs *es,
struct buf *bp;
uint32_t e2fs_descpb;
- fs->e2fs_bsize = EXT2_MIN_BLOCK_SIZE << es->e2fs_log_bsize;
fs->e2fs_bshift = EXT2_MIN_BLOCK_LOG_SIZE + es->e2fs_log_bsize;
+ fs->e2fs_bsize = 1U << fs->e2fs_bshift;
fs->e2fs_fsbtodb = es->e2fs_log_bsize + 1;
fs->e2fs_qbmask = fs->e2fs_bsize - 1;
fs->e2fs_fsize = EXT2_MIN_FRAG_SIZE << es->e2fs_log_fsize;
@@ -527,6 +527,7 @@ ext2_mountfs(struct vnode *devvp, struct mount *mp)
int ronly;
int i, size;
int32_t *lp;
+ int32_t e2fs_maxcontig;
ronly = vfs_flagopt(mp->mnt_optnew, "ro", NULL, 0);
/* XXX: use VOP_ACESS to check FS perms */
@@ -601,12 +602,8 @@ ext2_mountfs(struct vnode *devvp, struct mount *mp)
* in ext2fs doesn't have these variables, so we can calculate
* them here.
*/
- ump->um_e2fs->e2fs_maxcontig = MAX(1, MAXPHYS / ump->um_e2fs->e2fs_bsize);
- if (ump->um_e2fs->e2fs_maxcontig > 0)
- ump->um_e2fs->e2fs_contigsumsize =
- MIN(ump->um_e2fs->e2fs_maxcontig, EXT2_MAXCONTIG);
- else
- ump->um_e2fs->e2fs_contigsumsize = 0;
+ e2fs_maxcontig = MAX(1, MAXPHYS / ump->um_e2fs->e2fs_bsize);
+ ump->um_e2fs->e2fs_contigsumsize = MIN(e2fs_maxcontig, EXT2_MAXCONTIG);
if (ump->um_e2fs->e2fs_contigsumsize > 0) {
size = ump->um_e2fs->e2fs_gcount * sizeof(int32_t);
ump->um_e2fs->e2fs_maxcluster = malloc(size, M_EXT2MNT, M_WAITOK);
diff --git a/sys/fs/ext2fs/ext2fs.h b/sys/fs/ext2fs/ext2fs.h
index c5a4c15..225e058 100644
--- a/sys/fs/ext2fs/ext2fs.h
+++ b/sys/fs/ext2fs/ext2fs.h
@@ -170,7 +170,6 @@ struct m_ext2fs {
char e2fs_wasvalid; /* valid at mount time */
off_t e2fs_maxfilesize;
struct ext2_gd *e2fs_gd; /* Group Descriptors */
- int32_t e2fs_maxcontig; /* max number of contiguous blks */
int32_t e2fs_contigsumsize; /* size of cluster summary array */
int32_t *e2fs_maxcluster; /* max cluster in each cyl group */
struct csum *e2fs_clustersum; /* cluster summary in each cyl group */
@@ -304,7 +303,6 @@ struct csum {
/*
* Macro-instructions used to manage several block sizes
*/
-#define EXT2_MIN_BLOCK_SIZE 1024
#define EXT2_MAX_BLOCK_SIZE 4096
#define EXT2_MIN_BLOCK_LOG_SIZE 10
#define EXT2_BLOCK_SIZE(s) ((s)->e2fs_bsize)
diff --git a/sys/fs/ext2fs/inode.h b/sys/fs/ext2fs/inode.h
index ec47216..6cb85ca 100644
--- a/sys/fs/ext2fs/inode.h
+++ b/sys/fs/ext2fs/inode.h
@@ -108,7 +108,6 @@ struct inode {
*/
#define i_shortlink i_db
#define i_rdev i_db[0]
-#define MAXSYMLINKLEN ((NDADDR + NIADDR) * sizeof(int32_t))
/* File permissions. */
#define IEXEC 0000100 /* Executable. */
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index a37b9f1..965ce31 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -640,7 +640,7 @@ interpret:
*/
p->p_flag |= P_EXEC;
if (p->p_pptr && (p->p_flag & P_PPWAIT)) {
- p->p_flag &= ~P_PPWAIT;
+ p->p_flag &= ~(P_PPWAIT | P_PPTRACE);
cv_broadcast(&p->p_pwait);
}
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index 3a9a3a4..82f0344 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -266,7 +266,7 @@ exit1(struct thread *td, int rv)
PROC_LOCK(p);
rv = p->p_xstat; /* Event handler could change exit status */
stopprofclock(p);
- p->p_flag &= ~(P_TRACED | P_PPWAIT);
+ p->p_flag &= ~(P_TRACED | P_PPWAIT | P_PPTRACE);
/*
* Stop the real interval timer. If the handler is currently
diff --git a/sys/kern/kern_ktr.c b/sys/kern/kern_ktr.c
index a11c76c..3202b9b 100644
--- a/sys/kern/kern_ktr.c
+++ b/sys/kern/kern_ktr.c
@@ -213,7 +213,11 @@ ktr_entries_initializer(void *dummy __unused)
ktr_mask = 0;
ktr_buf = malloc(sizeof(*ktr_buf) * KTR_ENTRIES, M_KTR,
M_WAITOK | M_ZERO);
- memcpy(ktr_buf, ktr_buf_init, sizeof(ktr_buf_init));
+ memcpy(ktr_buf, ktr_buf_init + ktr_idx,
+ (KTR_BOOT_ENTRIES - ktr_idx) * sizeof(*ktr_buf));
+ if (ktr_idx != 0)
+ memcpy(ktr_buf + KTR_BOOT_ENTRIES - ktr_idx, ktr_buf_init,
+ ktr_idx * sizeof(*ktr_buf));
ktr_entries = KTR_ENTRIES;
ktr_mask = mask;
}
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index e28bdc4..5bb49a8 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -2618,7 +2618,7 @@ issignal(struct thread *td, int stop_allowed)
sigqueue_delete(&p->p_sigqueue, sig);
continue;
}
- if (p->p_flag & P_TRACED && (p->p_flag & P_PPWAIT) == 0) {
+ if (p->p_flag & P_TRACED && (p->p_flag & P_PPTRACE) == 0) {
/*
* If traced, always stop.
* Remove old signal from queue before the stop.
diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c
index b1f8145..63de37a 100644
--- a/sys/kern/sys_process.c
+++ b/sys/kern/sys_process.c
@@ -822,6 +822,8 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
case PT_TRACE_ME:
/* set my trace flag and "owner" so it can read/write me */
p->p_flag |= P_TRACED;
+ if (p->p_flag & P_PPWAIT)
+ p->p_flag |= P_PPTRACE;
p->p_oppid = p->p_pptr->p_pid;
break;
diff --git a/sys/net/if_var.h b/sys/net/if_var.h
index 2ec73e4..7fcbd38 100644
--- a/sys/net/if_var.h
+++ b/sys/net/if_var.h
@@ -622,6 +622,45 @@ drbr_enqueue(struct ifnet *ifp, struct buf_ring *br, struct mbuf *m)
}
static __inline void
+drbr_putback(struct ifnet *ifp, struct buf_ring *br, struct mbuf *new)
+{
+ /*
+ * The top of the list needs to be swapped
+ * for this one.
+ */
+#ifdef ALTQ
+ if (ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd)) {
+ /*
+ * Peek in altq case dequeued it
+ * so put it back.
+ */
+ IFQ_DRV_PREPEND(&ifp->if_snd, new);
+ return;
+ }
+#endif
+ buf_ring_putback_sc(br, new);
+}
+
+static __inline struct mbuf *
+drbr_peek(struct ifnet *ifp, struct buf_ring *br)
+{
+#ifdef ALTQ
+ struct mbuf *m;
+ if (ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd)) {
+ /*
+ * Pull it off like a dequeue
+ * since drbr_advance() does nothing
+ * for altq and drbr_putback() will
+ * use the old prepend function.
+ */
+ IFQ_DEQUEUE(&ifp->if_snd, m);
+ return (m);
+ }
+#endif
+ return(buf_ring_peek(br));
+}
+
+static __inline void
drbr_flush(struct ifnet *ifp, struct buf_ring *br)
{
struct mbuf *m;
@@ -648,7 +687,7 @@ drbr_dequeue(struct ifnet *ifp, struct buf_ring *br)
#ifdef ALTQ
struct mbuf *m;
- if (ALTQ_IS_ENABLED(&ifp->if_snd)) {
+ if (ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd)) {
IFQ_DEQUEUE(&ifp->if_snd, m);
return (m);
}
@@ -656,6 +695,18 @@ drbr_dequeue(struct ifnet *ifp, struct buf_ring *br)
return (buf_ring_dequeue_sc(br));
}
+static __inline void
+drbr_advance(struct ifnet *ifp, struct buf_ring *br)
+{
+#ifdef ALTQ
+ /* Nothing to do here since peek dequeues in altq case */
+ if (ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd))
+ return;
+#endif
+ return (buf_ring_advance_sc(br));
+}
+
+
static __inline struct mbuf *
drbr_dequeue_cond(struct ifnet *ifp, struct buf_ring *br,
int (*func) (struct mbuf *, void *), void *arg)
diff --git a/sys/net80211/ieee80211_action.c b/sys/net80211/ieee80211_action.c
index 44543b6..e3576d6 100644
--- a/sys/net80211/ieee80211_action.c
+++ b/sys/net80211/ieee80211_action.c
@@ -67,10 +67,8 @@ static ieee80211_send_action_func *meshpl_send_action[8] = {
send_inval, send_inval, send_inval, send_inval,
send_inval, send_inval, send_inval, send_inval,
};
-static ieee80211_send_action_func *meshlm_send_action[4] = {
+static ieee80211_send_action_func *meshaction_send_action[12] = {
send_inval, send_inval, send_inval, send_inval,
-};
-static ieee80211_send_action_func *hwmp_send_action[8] = {
send_inval, send_inval, send_inval, send_inval,
send_inval, send_inval, send_inval, send_inval,
};
@@ -100,18 +98,10 @@ ieee80211_send_action_register(int cat, int act, ieee80211_send_action_func *f)
meshpl_send_action[act] = f;
return 0;
case IEEE80211_ACTION_CAT_MESH:
- switch (act) {
- case IEEE80211_ACTION_MESH_LMETRIC:
- if (act >= N(meshlm_send_action))
- break;
- meshlm_send_action[act] = f;
- return 0;
- case IEEE80211_ACTION_MESH_HWMP:
- if (act >= N(hwmp_send_action))
- break;
- hwmp_send_action[act] = f;
- return 0;
- }
+ if (act >= N(meshaction_send_action))
+ break;
+ meshaction_send_action[act] = f;
+ return 0;
break;
case IEEE80211_ACTION_CAT_VENDOR:
if (act >= N(vendor_send_action))
@@ -149,16 +139,8 @@ ieee80211_send_action(struct ieee80211_node *ni, int cat, int act, void *sa)
f = meshpl_send_action[act];
break;
case IEEE80211_ACTION_CAT_MESH:
- switch (act) {
- case IEEE80211_ACTION_MESH_LMETRIC:
- if (act < N(meshlm_send_action))
- f = meshlm_send_action[act];
- break;
- case IEEE80211_ACTION_MESH_HWMP:
- if (act < N(hwmp_send_action))
- f = hwmp_send_action[act];
- break;
- }
+ if (act < N(meshaction_send_action))
+ f = meshaction_send_action[act];
break;
case IEEE80211_ACTION_CAT_VENDOR:
if (act < N(vendor_send_action))
@@ -188,10 +170,8 @@ static ieee80211_recv_action_func *meshpl_recv_action[8] = {
recv_inval, recv_inval, recv_inval, recv_inval,
recv_inval, recv_inval, recv_inval, recv_inval,
};
-static ieee80211_recv_action_func *meshlm_recv_action[4] = {
+static ieee80211_recv_action_func *meshaction_recv_action[12] = {
recv_inval, recv_inval, recv_inval, recv_inval,
-};
-static ieee80211_recv_action_func *hwmp_recv_action[8] = {
recv_inval, recv_inval, recv_inval, recv_inval,
recv_inval, recv_inval, recv_inval, recv_inval,
};
@@ -221,19 +201,10 @@ ieee80211_recv_action_register(int cat, int act, ieee80211_recv_action_func *f)
meshpl_recv_action[act] = f;
return 0;
case IEEE80211_ACTION_CAT_MESH:
- switch (act) {
- case IEEE80211_ACTION_MESH_LMETRIC:
- if (act >= N(meshlm_recv_action))
- break;
- meshlm_recv_action[act] = f;
- return 0;
- case IEEE80211_ACTION_MESH_HWMP:
- if (act >= N(hwmp_recv_action))
- break;
- hwmp_recv_action[act] = f;
- return 0;
- }
- break;
+ if (act >= N(meshaction_recv_action))
+ break;
+ meshaction_recv_action[act] = f;
+ return 0;
case IEEE80211_ACTION_CAT_VENDOR:
if (act >= N(vendor_recv_action))
break;
@@ -257,6 +228,7 @@ ieee80211_recv_action(struct ieee80211_node *ni,
{
#define N(a) (sizeof(a) / sizeof(a[0]))
ieee80211_recv_action_func *f = recv_inval;
+ struct ieee80211vap *vap = ni->ni_vap;
const struct ieee80211_action *ia =
(const struct ieee80211_action *) frm;
@@ -274,16 +246,17 @@ ieee80211_recv_action(struct ieee80211_node *ni,
f = meshpl_recv_action[ia->ia_action];
break;
case IEEE80211_ACTION_CAT_MESH:
- switch (ia->ia_action) {
- case IEEE80211_ACTION_MESH_LMETRIC:
- if (ia->ia_action < N(meshlm_recv_action))
- f = meshlm_recv_action[ia->ia_action];
- break;
- case IEEE80211_ACTION_MESH_HWMP:
- if (ia->ia_action < N(hwmp_recv_action))
- f = hwmp_recv_action[ia->ia_action];
+ if (ni == vap->iv_bss ||
+ ni->ni_mlstate != IEEE80211_NODE_MESH_ESTABLISHED) {
+ IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_MESH,
+ ni->ni_macaddr, NULL,
+ "peer link not yet established (%d), cat %s act %u",
+ ni->ni_mlstate, "mesh action", ia->ia_action);
+ vap->iv_stats.is_mesh_nolink++;
break;
}
+ if (ia->ia_action < N(meshaction_recv_action))
+ f = meshaction_recv_action[ia->ia_action];
break;
case IEEE80211_ACTION_CAT_VENDOR:
if (ia->ia_action < N(vendor_recv_action))
diff --git a/sys/net80211/ieee80211_ddb.c b/sys/net80211/ieee80211_ddb.c
index c869571..6f7dabf 100644
--- a/sys/net80211/ieee80211_ddb.c
+++ b/sys/net80211/ieee80211_ddb.c
@@ -63,9 +63,9 @@ __FBSDID("$FreeBSD$");
} while (0)
static void _db_show_sta(const struct ieee80211_node *);
-static void _db_show_vap(const struct ieee80211vap *, int);
+static void _db_show_vap(const struct ieee80211vap *, int, int);
static void _db_show_com(const struct ieee80211com *,
- int showvaps, int showsta, int showprocs);
+ int showvaps, int showsta, int showmesh, int showprocs);
static void _db_show_node_table(const char *tag,
const struct ieee80211_node_table *);
@@ -103,7 +103,7 @@ DB_SHOW_COMMAND(statab, db_show_statab)
DB_SHOW_COMMAND(vap, db_show_vap)
{
- int i, showprocs = 0;
+ int i, showmesh = 0, showprocs = 0;
if (!have_addr) {
db_printf("usage: show vap <addr>\n");
@@ -113,18 +113,22 @@ DB_SHOW_COMMAND(vap, db_show_vap)
switch (modif[i]) {
case 'a':
showprocs = 1;
+ showmesh = 1;
+ break;
+ case 'm':
+ showmesh = 1;
break;
case 'p':
showprocs = 1;
break;
}
- _db_show_vap((const struct ieee80211vap *) addr, showprocs);
+ _db_show_vap((const struct ieee80211vap *) addr, showmesh, showprocs);
}
DB_SHOW_COMMAND(com, db_show_com)
{
const struct ieee80211com *ic;
- int i, showprocs = 0, showvaps = 0, showsta = 0;
+ int i, showprocs = 0, showvaps = 0, showsta = 0, showmesh = 0;
if (!have_addr) {
db_printf("usage: show com <addr>\n");
@@ -133,11 +137,14 @@ DB_SHOW_COMMAND(com, db_show_com)
for (i = 0; modif[i] != '\0'; i++)
switch (modif[i]) {
case 'a':
- showsta = showvaps = showprocs = 1;
+ showsta = showmesh = showvaps = showprocs = 1;
break;
case 's':
showsta = 1;
break;
+ case 'm':
+ showmesh = 1;
+ break;
case 'v':
showvaps = 1;
break;
@@ -147,7 +154,7 @@ DB_SHOW_COMMAND(com, db_show_com)
}
ic = (const struct ieee80211com *) addr;
- _db_show_com(ic, showvaps, showsta, showprocs);
+ _db_show_com(ic, showvaps, showsta, showmesh, showprocs);
}
DB_SHOW_ALL_COMMAND(vaps, db_show_all_vaps)
@@ -178,7 +185,7 @@ DB_SHOW_ALL_COMMAND(vaps, db_show_all_vaps)
vap->iv_ifp->if_xname, vap);
db_printf("\n");
} else
- _db_show_com(ic, 1, 1, 1);
+ _db_show_com(ic, 1, 1, 1, 1);
}
}
}
@@ -330,7 +337,7 @@ _db_show_tdma(const char *sep, const struct ieee80211_tdma_state *ts, int showpr
#endif /* IEEE80211_SUPPORT_TDMA */
static void
-_db_show_vap(const struct ieee80211vap *vap, int showprocs)
+_db_show_vap(const struct ieee80211vap *vap, int showmesh, int showprocs)
{
const struct ieee80211com *ic = vap->iv_ic;
int i;
@@ -341,6 +348,10 @@ _db_show_vap(const struct ieee80211vap *vap, int showprocs)
db_printf("\n");
db_printf("\topmode %s", ieee80211_opmode_name[vap->iv_opmode]);
+#ifdef IEEE80211_SUPPORT_MESH
+ if (vap->iv_opmode == IEEE80211_M_MBSS)
+ db_printf("(%p)", vap->iv_mesh);
+#endif
db_printf(" state %s", ieee80211_state_name[vap->iv_state]);
db_printf(" ifp %p(%s)", vap->iv_ifp, vap->iv_ifp->if_xname);
db_printf("\n");
@@ -472,6 +483,10 @@ _db_show_vap(const struct ieee80211vap *vap, int showprocs)
db_printf(" acl %p", vap->iv_acl);
db_printf(" as %p", vap->iv_as);
db_printf("\n");
+#ifdef IEEE80211_SUPPORT_MESH
+ if (showmesh && vap->iv_mesh != NULL)
+ _db_show_mesh(vap->iv_mesh);
+#endif
#ifdef IEEE80211_SUPPORT_TDMA
if (vap->iv_tdma != NULL)
_db_show_tdma("\t", vap->iv_tdma, showprocs);
@@ -495,7 +510,8 @@ _db_show_vap(const struct ieee80211vap *vap, int showprocs)
}
static void
-_db_show_com(const struct ieee80211com *ic, int showvaps, int showsta, int showprocs)
+_db_show_com(const struct ieee80211com *ic, int showvaps, int showsta,
+ int showmesh, int showprocs)
{
struct ieee80211vap *vap;
@@ -651,7 +667,7 @@ _db_show_com(const struct ieee80211com *ic, int showvaps, int showsta, int showp
if (showvaps && !TAILQ_EMPTY(&ic->ic_vaps)) {
db_printf("\n");
TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next)
- _db_show_vap(vap, showprocs);
+ _db_show_vap(vap, showmesh, showprocs);
}
if (showsta && !TAILQ_EMPTY(&ic->ic_sta.nt_node)) {
const struct ieee80211_node_table *nt = &ic->ic_sta;
diff --git a/sys/net80211/ieee80211_hwmp.c b/sys/net80211/ieee80211_hwmp.c
index 2f8ec85..414ac53 100644
--- a/sys/net80211/ieee80211_hwmp.c
+++ b/sys/net80211/ieee80211_hwmp.c
@@ -68,8 +68,7 @@ static void hwmp_vattach(struct ieee80211vap *);
static void hwmp_vdetach(struct ieee80211vap *);
static int hwmp_newstate(struct ieee80211vap *,
enum ieee80211_state, int);
-static int hwmp_send_action(struct ieee80211_node *,
- const uint8_t [IEEE80211_ADDR_LEN],
+static int hwmp_send_action(struct ieee80211vap *,
const uint8_t [IEEE80211_ADDR_LEN],
uint8_t *, size_t);
static uint8_t * hwmp_add_meshpreq(uint8_t *,
@@ -86,23 +85,20 @@ static void hwmp_rootmode_rann_cb(void *);
static void hwmp_recv_preq(struct ieee80211vap *, struct ieee80211_node *,
const struct ieee80211_frame *,
const struct ieee80211_meshpreq_ie *);
-static int hwmp_send_preq(struct ieee80211_node *,
- const uint8_t [IEEE80211_ADDR_LEN],
+static int hwmp_send_preq(struct ieee80211vap *,
const uint8_t [IEEE80211_ADDR_LEN],
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 *);
-static int hwmp_send_prep(struct ieee80211_node *,
- const uint8_t [IEEE80211_ADDR_LEN],
+static int hwmp_send_prep(struct ieee80211vap *,
const uint8_t [IEEE80211_ADDR_LEN],
struct ieee80211_meshprep_ie *);
static void hwmp_recv_perr(struct ieee80211vap *, struct ieee80211_node *,
const struct ieee80211_frame *,
const struct ieee80211_meshperr_ie *);
-static int hwmp_send_perr(struct ieee80211_node *,
- const uint8_t [IEEE80211_ADDR_LEN],
+static int hwmp_send_perr(struct ieee80211vap *,
const uint8_t [IEEE80211_ADDR_LEN],
struct ieee80211_meshperr_ie *);
static void hwmp_senderror(struct ieee80211vap *,
@@ -111,8 +107,7 @@ static void hwmp_senderror(struct ieee80211vap *,
static void hwmp_recv_rann(struct ieee80211vap *, struct ieee80211_node *,
const struct ieee80211_frame *,
const struct ieee80211_meshrann_ie *);
-static int hwmp_send_rann(struct ieee80211_node *,
- const uint8_t [IEEE80211_ADDR_LEN],
+static int hwmp_send_rann(struct ieee80211vap *,
const uint8_t [IEEE80211_ADDR_LEN],
struct ieee80211_meshrann_ie *);
static struct ieee80211_node *
@@ -588,17 +583,30 @@ hwmp_recv_action_meshpath(struct ieee80211_node *ni,
}
static int
-hwmp_send_action(struct ieee80211_node *ni,
- const uint8_t sa[IEEE80211_ADDR_LEN],
+hwmp_send_action(struct ieee80211vap *vap,
const uint8_t da[IEEE80211_ADDR_LEN],
uint8_t *ie, size_t len)
{
- struct ieee80211vap *vap = ni->ni_vap;
- struct ieee80211com *ic = ni->ni_ic;
+ struct ieee80211_node *ni;
+ struct ieee80211com *ic;
struct ieee80211_bpf_params params;
struct mbuf *m;
uint8_t *frm;
+ if (IEEE80211_IS_MULTICAST(da)) {
+ ni = ieee80211_ref_node(vap->iv_bss);
+#ifdef IEEE80211_DEBUG_REFCNT
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE,
+ "ieee80211_ref_node (%s:%u) %p<%s> refcnt %d\n",
+ __func__, __LINE__,
+ ni, ether_sprintf(ni->ni_macaddr),
+ ieee80211_node_refcnt(ni)+1);
+#endif
+ ieee80211_ref_node(ni);
+ }
+ else
+ ni = ieee80211_mesh_find_txnode(vap, da);
+
if (vap->iv_state == IEEE80211_S_CAC) {
IEEE80211_NOTE(vap, IEEE80211_MSG_OUTPUT, ni,
"block %s frame in CAC state", "HWMP action");
@@ -607,19 +615,7 @@ hwmp_send_action(struct ieee80211_node *ni,
}
KASSERT(ni != NULL, ("null node"));
- /*
- * Hold a reference on the node so it doesn't go away until after
- * the xmit is complete all the way in the driver. On error we
- * will remove our reference.
- */
-#ifdef IEEE80211_DEBUG_REFCNT
- IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE,
- "ieee80211_ref_node (%s:%u) %p<%s> refcnt %d\n",
- __func__, __LINE__,
- ni, ether_sprintf(ni->ni_macaddr),
- ieee80211_node_refcnt(ni)+1);
-#endif
- ieee80211_ref_node(ni);
+ ic = ni->ni_ic;
m = ieee80211_getmgtframe(&frm,
ic->ic_headroom + sizeof(struct ieee80211_frame),
@@ -660,7 +656,7 @@ hwmp_send_action(struct ieee80211_node *ni,
}
ieee80211_send_setup(ni, m,
IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_ACTION,
- IEEE80211_NONQOS_TID, sa, da, sa);
+ IEEE80211_NONQOS_TID, vap->iv_myaddr, da, vap->iv_myaddr);
m->m_flags |= M_ENCAP; /* mark encapsulated */
IEEE80211_NODE_STAT(ni, tx_mgmt);
@@ -805,19 +801,23 @@ static void
hwmp_rootmode_setup(struct ieee80211vap *vap)
{
struct ieee80211_hwmp_state *hs = vap->iv_hwmp;
+ struct ieee80211_mesh_state *ms = vap->iv_mesh;
switch (hs->hs_rootmode) {
case IEEE80211_HWMP_ROOTMODE_DISABLED:
callout_drain(&hs->hs_roottimer);
+ ms->ms_flags &= ~IEEE80211_MESHFLAGS_ROOT;
break;
case IEEE80211_HWMP_ROOTMODE_NORMAL:
case IEEE80211_HWMP_ROOTMODE_PROACTIVE:
callout_reset(&hs->hs_roottimer, ieee80211_hwmp_rootint,
hwmp_rootmode_cb, vap);
+ ms->ms_flags |= IEEE80211_MESHFLAGS_ROOT;
break;
case IEEE80211_HWMP_ROOTMODE_RANN:
callout_reset(&hs->hs_roottimer, ieee80211_hwmp_rannint,
hwmp_rootmode_rann_cb, vap);
+ ms->ms_flags |= IEEE80211_MESHFLAGS_ROOT;
break;
}
}
@@ -858,8 +858,8 @@ hwmp_rootmode_cb(void *arg)
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,
- NULL, NULL); /* NB: we enforce rate check ourself */
+ /* NB: we enforce rate check ourself */
+ hwmp_send_preq(vap, broadcastaddr, &preq, NULL, NULL);
hwmp_rootmode_setup(vap);
}
#undef PREQ_TFLAGS
@@ -892,10 +892,49 @@ hwmp_rootmode_rann_cb(void *arg)
rann.rann_metric = IEEE80211_MESHLMETRIC_INITIALVAL;
vap->iv_stats.is_hwmp_rootrann++;
- hwmp_send_rann(vap->iv_bss, vap->iv_myaddr, broadcastaddr, &rann);
+ hwmp_send_rann(vap, broadcastaddr, &rann);
hwmp_rootmode_setup(vap);
}
+/*
+ * Update forwarding information to TA if metric improves.
+ */
+static void
+hwmp_update_transmitter(struct ieee80211vap *vap, struct ieee80211_node *ni,
+ const char *hwmp_frame)
+{
+ struct ieee80211_mesh_state *ms = vap->iv_mesh;
+ struct ieee80211_mesh_route *rttran = NULL; /* Transmitter */
+ int metric = 0;
+
+ rttran = ieee80211_mesh_rt_find(vap, ni->ni_macaddr);
+ if (rttran == NULL) {
+ rttran = ieee80211_mesh_rt_add(vap, ni->ni_macaddr);
+ if (rttran == NULL) {
+ IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+ "unable to add path to transmitter %6D of %s",
+ ni->ni_macaddr, ":", hwmp_frame);
+ vap->iv_stats.is_mesh_rtaddfailed++;
+ return;
+ }
+ }
+ metric = ms->ms_pmetric->mpm_metric(ni);
+ if (!(rttran->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) ||
+ rttran->rt_metric > metric)
+ {
+ IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+ "%s path to transmiter %6D of %s, metric %d:%d",
+ rttran->rt_flags & IEEE80211_MESHRT_FLAGS_VALID ?
+ "prefer" : "update", ni->ni_macaddr, ":", hwmp_frame,
+ rttran->rt_metric, metric);
+ IEEE80211_ADDR_COPY(rttran->rt_nexthop, ni->ni_macaddr);
+ rttran->rt_metric = metric;
+ rttran->rt_nhops = 1;
+ ieee80211_mesh_rt_update(rttran, ms->ms_ppath->mpp_inact);
+ rttran->rt_flags = IEEE80211_MESHRT_FLAGS_VALID;
+ }
+}
+
#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
@@ -914,9 +953,6 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni,
ieee80211_hwmp_seq preqid; /* last seen preqid for orig */
uint32_t metric = 0;
- if (ni == vap->iv_bss ||
- ni->ni_mlstate != IEEE80211_NODE_MESH_ESTABLISHED)
- return;
/*
* Ignore PREQs from us. Could happen because someone forward it
* back to us.
@@ -995,12 +1031,15 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni,
rtorig->rt_metric = metric;
rtorig->rt_nhops = preq->preq_hopcount + 1;
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)) ||
- preqid >= preq->preq_id) {
+ /* Path to orig is valid now.
+ * NB: we know it can't be Proxy, and if it is GATE
+ * it will be marked below.
+ */
+ 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 &&
+ preqid >= preq->preq_id)) {
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
"discard PREQ from %6D, old seqno %u <= %u,"
" or old preqid %u < %u",
@@ -1010,17 +1049,17 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni,
return;
}
- /*
- * Forwarding information for transmitter mesh STA
- * [OPTIONAL: if metric improved]
- */
+ /* Update forwarding information to TA if metric improves. */
+ hwmp_update_transmitter(vap, ni, "PREQ");
/*
* Check if the PREQ is addressed to us.
- * or a Proxy currently supplied by us.
+ * or a Proxy currently gated by us.
*/
if (IEEE80211_ADDR_EQ(vap->iv_myaddr, PREQ_TADDR(0)) ||
- (rttarg != NULL &&
+ (ms->ms_flags & IEEE80211_MESHFLAGS_GATE &&
+ rttarg != NULL &&
+ IEEE80211_ADDR_EQ(vap->iv_myaddr, rttarg->rt_mesh_gate) &&
rttarg->rt_flags & IEEE80211_MESHRT_FLAGS_PROXY &&
rttarg->rt_flags & IEEE80211_MESHRT_FLAGS_VALID)) {
/*
@@ -1031,6 +1070,7 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni,
prep.prep_flags = 0;
prep.prep_hopcount = 0;
+ prep.prep_metric = IEEE80211_MESHLMETRIC_INITIALVAL;
IEEE80211_ADDR_COPY(prep.prep_targetaddr, vap->iv_myaddr);
if (rttarg != NULL && /* if NULL it means we are the target */
rttarg->rt_flags & IEEE80211_MESHRT_FLAGS_PROXY) {
@@ -1042,6 +1082,7 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni,
/* update proxy seqno to HWMP seqno */
rttarg->rt_ext_seq = hs->hs_seq;
prep.prep_hopcount = rttarg->rt_nhops;
+ prep.prep_metric = rttarg->rt_metric;
IEEE80211_ADDR_COPY(prep.prep_targetaddr, rttarg->rt_mesh_gate);
}
/*
@@ -1050,13 +1091,12 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni,
prep.prep_ttl = ms->ms_ttl;
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);
+ hwmp_send_prep(vap, wh->i_addr2, &prep);
return;
}
/* we may update our proxy information for the orig external */
@@ -1088,6 +1128,16 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni,
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
"root mesh station @ %6D", preq->preq_origaddr, ":");
+ /* Check if root is a mesh gate, mark it */
+ if (preq->preq_flags & IEEE80211_MESHPREQ_FLAGS_GATE) {
+ struct ieee80211_mesh_gate_route *gr;
+
+ rtorig->rt_flags |= IEEE80211_MESHRT_FLAGS_GATE;
+ gr = ieee80211_mesh_mark_gate(vap, preq->preq_origaddr,
+ rtorig);
+ gr->gr_lastseq = 0; /* NOT GANN */
+ }
+
/*
* Reply with a PREP if we don't have a path to the root
* or if the root sent us a proactive PREQ.
@@ -1105,8 +1155,7 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni,
IEEE80211_ADDR_COPY(prep.prep_targetaddr,
vap->iv_myaddr);
prep.prep_targetseq = ++hs->hs_seq;
- hwmp_send_prep(vap->iv_bss, vap->iv_myaddr,
- rtorig->rt_nexthop, &prep);
+ hwmp_send_prep(vap, rtorig->rt_nexthop, &prep);
}
}
@@ -1121,9 +1170,11 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni,
/*
* We have a valid route to this node.
+ * NB: if target is proxy dont reply.
*/
if (rttarg != NULL &&
- (rttarg->rt_flags & IEEE80211_MESHRT_FLAGS_VALID)) {
+ rttarg->rt_flags & IEEE80211_MESHRT_FLAGS_VALID &&
+ !(rttarg->rt_flags & IEEE80211_MESHRT_FLAGS_PROXY)) {
/*
* Check if we can send an intermediate Path Reply,
* i.e., Target Only bit is not set and target is not
@@ -1147,8 +1198,7 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni,
IEEE80211_ADDR_COPY(&prep.prep_origaddr,
preq->preq_origaddr);
prep.prep_origseq = hrorig->hr_seq;
- hwmp_send_prep(ni, vap->iv_myaddr,
- rtorig->rt_nexthop, &prep);
+ hwmp_send_prep(vap, rtorig->rt_nexthop, &prep);
/*
* Set TO and unset RF bits because we have
@@ -1167,8 +1217,7 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni,
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);
+ hwmp_send_preq(vap, broadcastaddr, &ppreq, NULL, NULL);
}
}
#undef PREQ_TFLAGS
@@ -1176,8 +1225,7 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni,
#undef PREQ_TSEQ
static int
-hwmp_send_preq(struct ieee80211_node *ni,
- const uint8_t sa[IEEE80211_ADDR_LEN],
+hwmp_send_preq(struct ieee80211vap *vap,
const uint8_t da[IEEE80211_ADDR_LEN],
struct ieee80211_meshpreq_ie *preq,
struct timeval *last, struct timeval *minint)
@@ -1206,7 +1254,7 @@ hwmp_send_preq(struct ieee80211_node *ni,
preq->preq_len = (preq->preq_flags & IEEE80211_MESHPREQ_FLAGS_AE ?
IEEE80211_MESHPREQ_BASE_SZ_AE : IEEE80211_MESHPREQ_BASE_SZ) +
preq->preq_tcount * IEEE80211_MESHPREQ_TRGT_SZ;
- return hwmp_send_action(ni, sa, da, (uint8_t *)preq, preq->preq_len+2);
+ return hwmp_send_action(vap, da, (uint8_t *)preq, preq->preq_len+2);
}
static void
@@ -1230,10 +1278,6 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni,
int is_encap;
struct ieee80211_node *ni_encap;
- if (ni == vap->iv_bss ||
- ni->ni_mlstate != IEEE80211_NODE_MESH_ESTABLISHED)
- return;
-
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
"received PREP, orig %6D, targ %6D", prep->prep_origaddr, ":",
prep->prep_targetaddr, ":");
@@ -1261,7 +1305,6 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni,
* 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) {
@@ -1316,6 +1359,9 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni,
}
rt->rt_flags |= IEEE80211_MESHRT_FLAGS_VALID; /* mark valid */
+ /* Update forwarding information to TA if metric improves */
+ hwmp_update_transmitter(vap, ni, "PREP");
+
/*
* If it's NOT for us, propagate the PREP
*/
@@ -1344,7 +1390,7 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni,
pprep.prep_hopcount += 1;
pprep.prep_ttl -= 1;
pprep.prep_metric += ms->ms_pmetric->mpm_metric(ni);
- hwmp_send_prep(ni, vap->iv_myaddr, rtorig->rt_nexthop, &pprep);
+ hwmp_send_prep(vap, rtorig->rt_nexthop, &pprep);
/* precursor list for the Target Mesh STA Address is updated */
}
@@ -1426,8 +1472,7 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni,
}
static int
-hwmp_send_prep(struct ieee80211_node *ni,
- const uint8_t sa[IEEE80211_ADDR_LEN],
+hwmp_send_prep(struct ieee80211vap *vap,
const uint8_t da[IEEE80211_ADDR_LEN],
struct ieee80211_meshprep_ie *prep)
{
@@ -1445,8 +1490,7 @@ hwmp_send_prep(struct ieee80211_node *ni,
prep->prep_ie = IEEE80211_ELEMID_MESHPREP;
prep->prep_len = prep->prep_flags & IEEE80211_MESHPREP_FLAGS_AE ?
IEEE80211_MESHPREP_BASE_SZ_AE : IEEE80211_MESHPREP_BASE_SZ;
- return hwmp_send_action(ni, sa, da, (uint8_t *)prep,
- prep->prep_len + 2);
+ return hwmp_send_action(vap, da, (uint8_t *)prep, prep->prep_len + 2);
}
#define PERR_DFLAGS(n) perr.perr_dests[n].dest_flags
@@ -1479,7 +1523,7 @@ hwmp_peerdown(struct ieee80211_node *ni)
PERR_DRCODE(0) = IEEE80211_REASON_MESH_PERR_DEST_UNREACH;
/* NB: flush everything passing through peer */
ieee80211_mesh_rt_flush_peer(vap, ni->ni_macaddr);
- hwmp_send_perr(vap->iv_bss, vap->iv_myaddr, broadcastaddr, &perr);
+ hwmp_send_perr(vap, broadcastaddr, &perr);
}
#undef PERR_DFLAGS
#undef PERR_DADDR
@@ -1502,10 +1546,6 @@ hwmp_recv_perr(struct ieee80211vap *vap, struct ieee80211_node *ni,
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, ":");
@@ -1525,7 +1565,7 @@ hwmp_recv_perr(struct ieee80211vap *vap, struct ieee80211_node *ni,
*/
for (i = 0; i < perr->perr_ndests; i++) {
rt = ieee80211_mesh_rt_find(vap, PERR_DADDR(i));
- if (rt == NULL || rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID)
+ if (rt == NULL)
continue;
if (!IEEE80211_ADDR_EQ(rt->rt_nexthop, wh->i_addr2))
continue;
@@ -1569,7 +1609,7 @@ hwmp_recv_perr(struct ieee80211vap *vap, struct ieee80211_node *ni,
"PERR, unknown reason code %u\n", PERR_DFLAGS(i));
goto done; /* XXX: stats?? */
}
- ieee80211_mesh_rt_flush_peer(vap, rt->rt_dest);
+ ieee80211_mesh_rt_flush_peer(vap, PERR_DADDR(i));
KASSERT(j < 32, ("PERR, error ndest >= 32 (%u)", j));
}
if (j == 0) {
@@ -1586,8 +1626,7 @@ hwmp_recv_perr(struct ieee80211vap *vap, struct ieee80211_node *ni,
"propagate PERR from %6D", wh->i_addr2, ":");
pperr->perr_ndests = j;
pperr->perr_ttl--;
- hwmp_send_perr(vap->iv_bss, vap->iv_myaddr, broadcastaddr,
- pperr);
+ hwmp_send_perr(vap, broadcastaddr, pperr);
}
done:
if (pperr != NULL)
@@ -1600,12 +1639,11 @@ done:
#undef PERR_DRCODE
static int
-hwmp_send_perr(struct ieee80211_node *ni,
- const uint8_t sa[IEEE80211_ADDR_LEN],
+hwmp_send_perr(struct ieee80211vap *vap,
const uint8_t da[IEEE80211_ADDR_LEN],
struct ieee80211_meshperr_ie *perr)
{
- struct ieee80211_hwmp_state *hs = ni->ni_vap->iv_hwmp;
+ struct ieee80211_hwmp_state *hs = vap->iv_hwmp;
int i;
uint8_t length = 0;
@@ -1636,7 +1674,7 @@ hwmp_send_perr(struct ieee80211_node *ni,
length += IEEE80211_MESHPERR_DEST_SZ;
}
perr->perr_len =length;
- return hwmp_send_action(ni, sa, da, (uint8_t *)perr, perr->perr_len+2);
+ return hwmp_send_action(vap, da, (uint8_t *)perr, perr->perr_len+2);
}
/*
@@ -1689,7 +1727,7 @@ hwmp_senderror(struct ieee80211vap *vap,
default:
KASSERT(0, ("unknown reason code for HWMP PERR (%u)", rcode));
}
- hwmp_send_perr(vap->iv_bss, vap->iv_myaddr, broadcastaddr, &perr);
+ hwmp_send_perr(vap, broadcastaddr, &perr);
}
#undef PERR_DFLAGS
#undef PEER_DADDR
@@ -1709,9 +1747,7 @@ hwmp_recv_rann(struct ieee80211vap *vap, struct ieee80211_node *ni,
struct ieee80211_meshrann_ie prann;
uint32_t metric = 0;
- if (ni == vap->iv_bss ||
- ni->ni_mlstate != IEEE80211_NODE_MESH_ESTABLISHED ||
- IEEE80211_ADDR_EQ(rann->rann_addr, vap->iv_myaddr))
+ if (IEEE80211_ADDR_EQ(rann->rann_addr, vap->iv_myaddr))
return;
rt = ieee80211_mesh_rt_find(vap, rann->rann_addr);
@@ -1751,6 +1787,15 @@ hwmp_recv_rann(struct ieee80211vap *vap, struct ieee80211_node *ni,
}
}
hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route);
+ /* Check if root is a mesh gate, mark it */
+ if (rann->rann_flags & IEEE80211_MESHRANN_FLAGS_GATE) {
+ struct ieee80211_mesh_gate_route *gr;
+
+ rt->rt_flags |= IEEE80211_MESHRT_FLAGS_GATE;
+ gr = ieee80211_mesh_mark_gate(vap, rann->rann_addr,
+ rt);
+ gr->gr_lastseq = 0; /* NOT GANN */
+ }
/* discovery timeout */
ieee80211_mesh_rt_update(rt,
ticks_to_msecs(ieee80211_hwmp_roottimeout));
@@ -1769,8 +1814,8 @@ hwmp_recv_rann(struct ieee80211vap *vap, struct ieee80211_node *ni,
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);
+ hwmp_send_preq(vap, wh->i_addr2, &preq, &hr->hr_lastrootconf,
+ &ieee80211_hwmp_rootconfint);
/* propagate a RANN */
if (rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID &&
@@ -1781,14 +1826,12 @@ hwmp_recv_rann(struct ieee80211vap *vap, struct ieee80211_node *ni,
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);
+ hwmp_send_rann(vap, broadcastaddr, &prann);
}
}
static int
-hwmp_send_rann(struct ieee80211_node *ni,
- const uint8_t sa[IEEE80211_ADDR_LEN],
+hwmp_send_rann(struct ieee80211vap *vap,
const uint8_t da[IEEE80211_ADDR_LEN],
struct ieee80211_meshrann_ie *rann)
{
@@ -1803,8 +1846,7 @@ hwmp_send_rann(struct ieee80211_node *ni,
*/
rann->rann_ie = IEEE80211_ELEMID_MESHRANN;
rann->rann_len = IEEE80211_MESHRANN_BASE_SZ;
- return hwmp_send_action(ni, sa, da, (uint8_t *)rann,
- rann->rann_len + 2);
+ return hwmp_send_action(vap, da, (uint8_t *)rann, rann->rann_len + 2);
}
#define PREQ_TFLAGS(n) preq.preq_targets[n].target_flags
@@ -1826,12 +1868,11 @@ hwmp_rediscover_cb(void *arg)
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 */
+ IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_ANY,
+ rt->rt_dest, "%s",
+ "max number of discovery, send queued frames to GATE");
+ ieee80211_mesh_forward_to_gates(vap, rt);
vap->iv_stats.is_mesh_fwd_nopath++;
- rt->rt_flags = 0; /* Mark invalid */
return ; /* XXX: flush queue? */
}
@@ -1860,9 +1901,8 @@ hwmp_rediscover_cb(void *arg)
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);
+ hwmp_send_preq(vap, broadcastaddr, &preq, &hr->hr_lastpreq,
+ &ieee80211_hwmp_preqminint);
callout_reset(&rt->rt_discovery,
ieee80211_hwmp_net_diameter_traversaltime * 2,
hwmp_rediscover_cb, rt);
@@ -1901,6 +1941,12 @@ hwmp_discover(struct ieee80211vap *vap,
}
hr = IEEE80211_MESH_ROUTE_PRIV(rt,
struct ieee80211_hwmp_route);
+ if (rt->rt_flags & IEEE80211_MESHRT_FLAGS_DISCOVER) {
+ IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_HWMP, dest,
+ "%s", "already discovering queue frame until path found");
+ sendpreq = 1;
+ goto done;
+ }
if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0) {
if (hr->hr_lastdiscovery != 0 &&
(ticks - hr->hr_lastdiscovery <
@@ -1908,7 +1954,7 @@ hwmp_discover(struct ieee80211vap *vap,
IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
dest, NULL, "%s",
"too frequent discovery requeust");
- /* XXX: stats? */
+ sendpreq = 1;
goto done;
}
hr->hr_lastdiscovery = ticks;
@@ -1952,9 +1998,8 @@ hwmp_discover(struct ieee80211vap *vap,
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);
+ hwmp_send_preq(vap, broadcastaddr, &preq,
+ &hr->hr_lastpreq, &ieee80211_hwmp_preqminint);
callout_reset(&rt->rt_discovery,
ieee80211_hwmp_net_diameter_traversaltime * 2,
hwmp_rediscover_cb, rt);
diff --git a/sys/net80211/ieee80211_input.c b/sys/net80211/ieee80211_input.c
index a9acad1..ebc4642 100644
--- a/sys/net80211/ieee80211_input.c
+++ b/sys/net80211/ieee80211_input.c
@@ -776,6 +776,10 @@ ieee80211_parse_action(struct ieee80211_node *ni, struct mbuf *m)
/* verify something */
break;
case IEEE80211_ACTION_MESH_GANN:
+ IEEE80211_VERIFY_LENGTH(efrm - frm,
+ sizeof(struct ieee80211_meshgann_ie),
+ return EINVAL);
+ break;
case IEEE80211_ACTION_MESH_CC:
case IEEE80211_ACTION_MESH_MCCA_SREQ:
case IEEE80211_ACTION_MESH_MCCA_SREP:
diff --git a/sys/net80211/ieee80211_ioctl.h b/sys/net80211/ieee80211_ioctl.h
index 2214b33..ee98026 100644
--- a/sys/net80211/ieee80211_ioctl.h
+++ b/sys/net80211/ieee80211_ioctl.h
@@ -342,6 +342,7 @@ struct ieee80211req_mesh_route {
#define IEEE80211_MESHRT_FLAGS_DISCOVER 0x01
#define IEEE80211_MESHRT_FLAGS_VALID 0x02
#define IEEE80211_MESHRT_FLAGS_PROXY 0x04
+#define IEEE80211_MESHRT_FLAGS_GATE 0x08
uint8_t imr_dest[IEEE80211_ADDR_LEN];
uint8_t imr_nexthop[IEEE80211_ADDR_LEN];
uint16_t imr_nhops;
diff --git a/sys/net80211/ieee80211_mesh.c b/sys/net80211/ieee80211_mesh.c
index 6ab76d9..6d323cd 100644
--- a/sys/net80211/ieee80211_mesh.c
+++ b/sys/net80211/ieee80211_mesh.c
@@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$");
#include <sys/proc.h>
#include <sys/sysctl.h>
+#include <net/bpf.h>
#include <net/if.h>
#include <net/if_media.h>
#include <net/if_llc.h>
@@ -59,6 +60,9 @@ __FBSDID("$FreeBSD$");
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_action.h>
+#ifdef IEEE80211_SUPPORT_SUPERG
+#include <net80211/ieee80211_superg.h>
+#endif
#include <net80211/ieee80211_input.h>
#include <net80211/ieee80211_mesh.h>
@@ -68,15 +72,16 @@ static int mesh_select_proto_metric(struct ieee80211vap *, const char *);
static void mesh_vattach(struct ieee80211vap *);
static int mesh_newstate(struct ieee80211vap *, enum ieee80211_state, int);
static void mesh_rt_cleanup_cb(void *);
+static void mesh_gatemode_setup(struct ieee80211vap *);
+static void mesh_gatemode_cb(void *);
static void mesh_linkchange(struct ieee80211_node *,
enum ieee80211_mesh_mlstate);
static void mesh_checkid(void *, struct ieee80211_node *);
static uint32_t mesh_generateid(struct ieee80211vap *);
static int mesh_checkpseq(struct ieee80211vap *,
const uint8_t [IEEE80211_ADDR_LEN], uint32_t);
-static struct ieee80211_node *
- mesh_find_txnode(struct ieee80211vap *,
- const uint8_t [IEEE80211_ADDR_LEN]);
+static void mesh_transmit_to_gate(struct ieee80211vap *, struct mbuf *,
+ struct ieee80211_mesh_route *);
static void mesh_forward(struct ieee80211vap *, struct mbuf *,
const struct ieee80211_meshcntl *);
static int mesh_input(struct ieee80211_node *, struct mbuf *, int, int);
@@ -99,11 +104,16 @@ uint32_t mesh_airtime_calc(struct ieee80211_node *);
*/
static SYSCTL_NODE(_net_wlan, OID_AUTO, mesh, CTLFLAG_RD, 0,
"IEEE 802.11s parameters");
+static int ieee80211_mesh_gateint = -1;
+SYSCTL_PROC(_net_wlan_mesh, OID_AUTO, gateint, CTLTYPE_INT | CTLFLAG_RW,
+ &ieee80211_mesh_gateint, 0, ieee80211_sysctl_msecs_ticks, "I",
+ "mesh gate interval (ms)");
static int ieee80211_mesh_retrytimeout = -1;
SYSCTL_PROC(_net_wlan_mesh, OID_AUTO, retrytimeout, CTLTYPE_INT | CTLFLAG_RW,
&ieee80211_mesh_retrytimeout, 0, ieee80211_sysctl_msecs_ticks, "I",
"Retry timeout (msec)");
static int ieee80211_mesh_holdingtimeout = -1;
+
SYSCTL_PROC(_net_wlan_mesh, OID_AUTO, holdingtimeout, CTLTYPE_INT | CTLFLAG_RW,
&ieee80211_mesh_holdingtimeout, 0, ieee80211_sysctl_msecs_ticks, "I",
"Holding state timeout (msec)");
@@ -111,10 +121,20 @@ static int ieee80211_mesh_confirmtimeout = -1;
SYSCTL_PROC(_net_wlan_mesh, OID_AUTO, confirmtimeout, CTLTYPE_INT | CTLFLAG_RW,
&ieee80211_mesh_confirmtimeout, 0, ieee80211_sysctl_msecs_ticks, "I",
"Confirm state timeout (msec)");
+static int ieee80211_mesh_backofftimeout = -1;
+SYSCTL_PROC(_net_wlan_mesh, OID_AUTO, backofftimeout, CTLTYPE_INT | CTLFLAG_RW,
+ &ieee80211_mesh_backofftimeout, 0, ieee80211_sysctl_msecs_ticks, "I",
+ "Backoff timeout (msec). This is to throutles peering forever when "
+ "not receving answer or is rejected by a neighbor");
static int ieee80211_mesh_maxretries = 2;
SYSCTL_INT(_net_wlan_mesh, OID_AUTO, maxretries, CTLTYPE_INT | CTLFLAG_RW,
&ieee80211_mesh_maxretries, 0,
"Maximum retries during peer link establishment");
+static int ieee80211_mesh_maxholding = 2;
+SYSCTL_INT(_net_wlan_mesh, OID_AUTO, maxholding, CTLTYPE_INT | CTLFLAG_RW,
+ &ieee80211_mesh_maxholding, 0,
+ "Maximum times we are allowed to transition to HOLDING state before "
+ "backinoff during peer link establishment");
static const uint8_t broadcastaddr[IEEE80211_ADDR_LEN] =
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
@@ -123,11 +143,13 @@ static ieee80211_recv_action_func mesh_recv_action_meshpeering_open;
static ieee80211_recv_action_func mesh_recv_action_meshpeering_confirm;
static ieee80211_recv_action_func mesh_recv_action_meshpeering_close;
static ieee80211_recv_action_func mesh_recv_action_meshlmetric;
+static ieee80211_recv_action_func mesh_recv_action_meshgate;
static ieee80211_send_action_func mesh_send_action_meshpeering_open;
static ieee80211_send_action_func mesh_send_action_meshpeering_confirm;
static ieee80211_send_action_func mesh_send_action_meshpeering_close;
static ieee80211_send_action_func mesh_send_action_meshlmetric;
+static ieee80211_send_action_func mesh_send_action_meshgate;
static const struct ieee80211_mesh_proto_metric mesh_metric_airtime = {
.mpm_descr = "AIRTIME",
@@ -153,7 +175,8 @@ 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");
+MALLOC_DEFINE(M_80211_MESH_RT, "80211mesh_rt", "802.11s routing table");
+MALLOC_DEFINE(M_80211_MESH_GT_RT, "80211mesh_gt", "802.11s known gates table");
/*
* Helper functions to manipulate the Mesh routing table.
@@ -488,6 +511,48 @@ mesh_select_proto_metric(struct ieee80211vap *vap, const char *name)
#undef N
static void
+mesh_gatemode_setup(struct ieee80211vap *vap)
+{
+ struct ieee80211_mesh_state *ms = vap->iv_mesh;
+
+ /*
+ * NB: When a mesh gate is running as a ROOT it shall
+ * not send out periodic GANNs but instead mark the
+ * mesh gate flag for the corresponding proactive PREQ
+ * and RANN frames.
+ */
+ if (ms->ms_flags & IEEE80211_MESHFLAGS_ROOT ||
+ (ms->ms_flags & IEEE80211_MESHFLAGS_GATE) == 0) {
+ callout_drain(&ms->ms_gatetimer);
+ return ;
+ }
+ callout_reset(&ms->ms_gatetimer, ieee80211_mesh_gateint,
+ mesh_gatemode_cb, vap);
+}
+
+static void
+mesh_gatemode_cb(void *arg)
+{
+ struct ieee80211vap *vap = (struct ieee80211vap *)arg;
+ struct ieee80211_mesh_state *ms = vap->iv_mesh;
+ struct ieee80211_meshgann_ie gann;
+
+ gann.gann_flags = 0; /* Reserved */
+ gann.gann_hopcount = 0;
+ gann.gann_ttl = ms->ms_ttl;
+ IEEE80211_ADDR_COPY(gann.gann_addr, vap->iv_myaddr);
+ gann.gann_seq = ms->ms_gateseq++;
+ gann.gann_interval = ieee80211_mesh_gateint;
+
+ IEEE80211_NOTE(vap, IEEE80211_MSG_MESH, vap->iv_bss,
+ "send broadcast GANN (seq %u)", gann.gann_seq);
+
+ ieee80211_send_action(vap->iv_bss, IEEE80211_ACTION_CAT_MESH,
+ IEEE80211_ACTION_MESH_GANN, &gann);
+ mesh_gatemode_setup(vap);
+}
+
+static void
ieee80211_mesh_init(void)
{
@@ -497,9 +562,11 @@ ieee80211_mesh_init(void)
/*
* Setup mesh parameters that depends on the clock frequency.
*/
+ ieee80211_mesh_gateint = msecs_to_ticks(10000);
ieee80211_mesh_retrytimeout = msecs_to_ticks(40);
ieee80211_mesh_holdingtimeout = msecs_to_ticks(40);
ieee80211_mesh_confirmtimeout = msecs_to_ticks(40);
+ ieee80211_mesh_backofftimeout = msecs_to_ticks(5000);
/*
* Register action frame handlers.
@@ -515,6 +582,8 @@ ieee80211_mesh_init(void)
mesh_recv_action_meshpeering_close);
ieee80211_recv_action_register(IEEE80211_ACTION_CAT_MESH,
IEEE80211_ACTION_MESH_LMETRIC, mesh_recv_action_meshlmetric);
+ ieee80211_recv_action_register(IEEE80211_ACTION_CAT_MESH,
+ IEEE80211_ACTION_MESH_GANN, mesh_recv_action_meshgate);
ieee80211_send_action_register(IEEE80211_ACTION_CAT_SELF_PROT,
IEEE80211_ACTION_MESHPEERING_OPEN,
@@ -528,6 +597,9 @@ ieee80211_mesh_init(void)
ieee80211_send_action_register(IEEE80211_ACTION_CAT_MESH,
IEEE80211_ACTION_MESH_LMETRIC,
mesh_send_action_meshlmetric);
+ ieee80211_send_action_register(IEEE80211_ACTION_CAT_MESH,
+ IEEE80211_ACTION_MESH_GANN,
+ mesh_send_action_meshgate);
/*
* Register Airtime Link Metric.
@@ -603,9 +675,12 @@ mesh_vattach(struct ieee80211vap *vap)
ms->ms_seq = 0;
ms->ms_flags = (IEEE80211_MESHFLAGS_AP | IEEE80211_MESHFLAGS_FWD);
ms->ms_ttl = IEEE80211_MESH_DEFAULT_TTL;
+ TAILQ_INIT(&ms->ms_known_gates);
TAILQ_INIT(&ms->ms_routes);
mtx_init(&ms->ms_rt_lock, "MBSS", "802.11s routing table", MTX_DEF);
callout_init(&ms->ms_cleantimer, CALLOUT_MPSAFE);
+ callout_init(&ms->ms_gatetimer, CALLOUT_MPSAFE);
+ ms->ms_gateseq = 0;
mesh_select_proto_metric(vap, "AIRTIME");
KASSERT(ms->ms_pmetric, ("ms_pmetric == NULL"));
mesh_select_proto_path(vap, "HWMP");
@@ -634,8 +709,10 @@ mesh_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
if (ostate != IEEE80211_S_SCAN)
ieee80211_cancel_scan(vap); /* background scan */
ni = vap->iv_bss; /* NB: no reference held */
- if (nstate != IEEE80211_S_RUN && ostate == IEEE80211_S_RUN)
+ if (nstate != IEEE80211_S_RUN && ostate == IEEE80211_S_RUN) {
callout_drain(&ms->ms_cleantimer);
+ callout_drain(&ms->ms_gatetimer);
+ }
switch (nstate) {
case IEEE80211_S_INIT:
switch (ostate) {
@@ -760,6 +837,7 @@ mesh_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
ieee80211_node_authorize(vap->iv_bss);
callout_reset(&ms->ms_cleantimer, ms->ms_ppath->mpp_inact,
mesh_rt_cleanup_cb, vap);
+ mesh_gatemode_setup(vap);
break;
default:
break;
@@ -780,6 +858,43 @@ mesh_rt_cleanup_cb(void *arg)
mesh_rt_cleanup_cb, vap);
}
+/*
+ * Mark a mesh STA as gate and return a pointer to it.
+ * If this is first time, we create a new gate route.
+ * Always update the path route to this mesh gate.
+ */
+struct ieee80211_mesh_gate_route *
+ieee80211_mesh_mark_gate(struct ieee80211vap *vap, const uint8_t *addr,
+ struct ieee80211_mesh_route *rt)
+{
+ struct ieee80211_mesh_state *ms = vap->iv_mesh;
+ struct ieee80211_mesh_gate_route *gr = NULL, *next;
+ int found = 0;
+
+ MESH_RT_LOCK(ms);
+ TAILQ_FOREACH_SAFE(gr, &ms->ms_known_gates, gr_next, next) {
+ if (IEEE80211_ADDR_EQ(gr->gr_addr, addr)) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found) {
+ /* New mesh gate add it to known table. */
+ IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, addr,
+ "%s", "stored new gate information from pro-PREQ.");
+ gr = malloc(ALIGN(sizeof(struct ieee80211_mesh_gate_route)),
+ M_80211_MESH_GT_RT, M_NOWAIT | M_ZERO);
+ IEEE80211_ADDR_COPY(gr->gr_addr, addr);
+ TAILQ_INSERT_TAIL(&ms->ms_known_gates, gr, gr_next);
+ }
+ gr->gr_route = rt;
+ /* TODO: link from path route to gate route */
+ MESH_RT_UNLOCK(ms);
+
+ return gr;
+}
+
/*
* Helper function to note the Mesh Peer Link FSM change.
@@ -891,8 +1006,8 @@ mesh_checkpseq(struct ieee80211vap *vap,
/*
* Iterate the routing table and locate the next hop.
*/
-static struct ieee80211_node *
-mesh_find_txnode(struct ieee80211vap *vap,
+struct ieee80211_node *
+ieee80211_mesh_find_txnode(struct ieee80211vap *vap,
const uint8_t dest[IEEE80211_ADDR_LEN])
{
struct ieee80211_mesh_route *rt;
@@ -900,16 +1015,220 @@ mesh_find_txnode(struct ieee80211vap *vap,
rt = ieee80211_mesh_rt_find(vap, dest);
if (rt == NULL)
return NULL;
- if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0 ||
- (rt->rt_flags & IEEE80211_MESHRT_FLAGS_PROXY)) {
+ if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0) {
IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, dest,
- "%s: !valid or proxy, flags 0x%x", __func__, rt->rt_flags);
+ "%s: !valid, flags 0x%x", __func__, rt->rt_flags);
/* XXX stat */
return NULL;
}
+ if (rt->rt_flags & IEEE80211_MESHRT_FLAGS_PROXY) {
+ rt = ieee80211_mesh_rt_find(vap, rt->rt_mesh_gate);
+ if (rt == NULL) return NULL;
+ if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0) {
+ IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, dest,
+ "%s: meshgate !valid, flags 0x%x", __func__,
+ rt->rt_flags);
+ /* XXX stat */
+ return NULL;
+ }
+ }
return ieee80211_find_txnode(vap, rt->rt_nexthop);
}
+static void
+mesh_transmit_to_gate(struct ieee80211vap *vap, struct mbuf *m,
+ struct ieee80211_mesh_route *rt_gate)
+{
+ struct ifnet *ifp = vap->iv_ifp;
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ifnet *parent = ic->ic_ifp;
+ struct ieee80211_node *ni;
+ struct ether_header *eh;
+ int error;
+
+ eh = mtod(m, struct ether_header *);
+ ni = ieee80211_mesh_find_txnode(vap, rt_gate->rt_dest);
+ if (ni == NULL) {
+ ifp->if_oerrors++;
+ m_freem(m);
+ return;
+ }
+
+ if ((ni->ni_flags & IEEE80211_NODE_PWR_MGT) &&
+ (m->m_flags & M_PWR_SAV) == 0) {
+ /*
+ * Station in power save mode; pass the frame
+ * to the 802.11 layer and continue. We'll get
+ * the frame back when the time is right.
+ * XXX lose WDS vap linkage?
+ */
+ (void) ieee80211_pwrsave(ni, m);
+ ieee80211_free_node(ni);
+ return;
+ }
+
+ /* calculate priority so drivers can find the tx queue */
+ if (ieee80211_classify(ni, m)) {
+ IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_OUTPUT,
+ eh->ether_dhost, NULL,
+ "%s", "classification failure");
+ vap->iv_stats.is_tx_classify++;
+ ifp->if_oerrors++;
+ m_freem(m);
+ ieee80211_free_node(ni);
+ return;
+ }
+ /*
+ * Stash the node pointer. Note that we do this after
+ * any call to ieee80211_dwds_mcast because that code
+ * uses any existing value for rcvif to identify the
+ * interface it (might have been) received on.
+ */
+ m->m_pkthdr.rcvif = (void *)ni;
+
+ BPF_MTAP(ifp, m); /* 802.3 tx */
+
+ /*
+ * Check if A-MPDU tx aggregation is setup or if we
+ * should try to enable it. The sta must be associated
+ * with HT and A-MPDU enabled for use. When the policy
+ * routine decides we should enable A-MPDU we issue an
+ * ADDBA request and wait for a reply. The frame being
+ * encapsulated will go out w/o using A-MPDU, or possibly
+ * it might be collected by the driver and held/retransmit.
+ * The default ic_ampdu_enable routine handles staggering
+ * ADDBA requests in case the receiver NAK's us or we are
+ * otherwise unable to establish a BA stream.
+ */
+ if ((ni->ni_flags & IEEE80211_NODE_AMPDU_TX) &&
+ (vap->iv_flags_ht & IEEE80211_FHT_AMPDU_TX) &&
+ (m->m_flags & M_EAPOL) == 0) {
+ int tid = WME_AC_TO_TID(M_WME_GETAC(m));
+ struct ieee80211_tx_ampdu *tap = &ni->ni_tx_ampdu[tid];
+
+ ieee80211_txampdu_count_packet(tap);
+ if (IEEE80211_AMPDU_RUNNING(tap)) {
+ /*
+ * Operational, mark frame for aggregation.
+ *
+ * XXX do tx aggregation here
+ */
+ m->m_flags |= M_AMPDU_MPDU;
+ } else if (!IEEE80211_AMPDU_REQUESTED(tap) &&
+ ic->ic_ampdu_enable(ni, tap)) {
+ /*
+ * Not negotiated yet, request service.
+ */
+ ieee80211_ampdu_request(ni, tap);
+ /* XXX hold frame for reply? */
+ }
+ }
+#ifdef IEEE80211_SUPPORT_SUPERG
+ else if (IEEE80211_ATH_CAP(vap, ni, IEEE80211_NODE_FF)) {
+ m = ieee80211_ff_check(ni, m);
+ if (m == NULL) {
+ /* NB: any ni ref held on stageq */
+ return;
+ }
+ }
+#endif /* IEEE80211_SUPPORT_SUPERG */
+ if (__predict_true((vap->iv_caps & IEEE80211_C_8023ENCAP) == 0)) {
+ /*
+ * Encapsulate the packet in prep for transmission.
+ */
+ m = ieee80211_encap(vap, ni, m);
+ if (m == NULL) {
+ /* NB: stat+msg handled in ieee80211_encap */
+ ieee80211_free_node(ni);
+ return;
+ }
+ }
+ error = parent->if_transmit(parent, m);
+ if (error != 0) {
+ m_freem(m);
+ ieee80211_free_node(ni);
+ } else {
+ ifp->if_opackets++;
+ }
+ ic->ic_lastdata = ticks;
+}
+
+/*
+ * Forward the queued frames to known valid mesh gates.
+ * Assume destination to be outside the MBSS (i.e. proxy entry),
+ * If no valid mesh gates are known silently discard queued frames.
+ * After transmitting frames to all known valid mesh gates, this route
+ * will be marked invalid, and a new path discovery will happen in the hopes
+ * that (at least) one of the mesh gates have a new proxy entry for us to use.
+ */
+void
+ieee80211_mesh_forward_to_gates(struct ieee80211vap *vap,
+ struct ieee80211_mesh_route *rt_dest)
+{
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ieee80211_mesh_state *ms = vap->iv_mesh;
+ struct ieee80211_mesh_route *rt_gate;
+ struct ieee80211_mesh_gate_route *gr = NULL, *gr_next;
+ struct mbuf *m, *mcopy, *next;
+
+ KASSERT( rt_dest->rt_flags == IEEE80211_MESHRT_FLAGS_DISCOVER,
+ ("Route is not marked with IEEE80211_MESHRT_FLAGS_DISCOVER"));
+
+ /* XXX: send to more than one valid mash gate */
+ MESH_RT_LOCK(ms);
+
+ m = ieee80211_ageq_remove(&ic->ic_stageq,
+ (struct ieee80211_node *)(uintptr_t)
+ ieee80211_mac_hash(ic, rt_dest->rt_dest));
+
+ TAILQ_FOREACH_SAFE(gr, &ms->ms_known_gates, gr_next, gr_next) {
+ rt_gate = gr->gr_route;
+ if (rt_gate == NULL) {
+ IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_HWMP,
+ rt_dest->rt_dest,
+ "mesh gate with no path %6D",
+ gr->gr_addr, ":");
+ continue;
+ }
+ if ((rt_gate->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0)
+ continue;
+ KASSERT(rt_gate->rt_flags & IEEE80211_MESHRT_FLAGS_GATE,
+ ("route not marked as a mesh gate"));
+ KASSERT((rt_gate->rt_flags &
+ IEEE80211_MESHRT_FLAGS_PROXY) == 0,
+ ("found mesh gate that is also marked porxy"));
+ /*
+ * convert route to a proxy route gated by the current
+ * mesh gate, this is needed so encap can built data
+ * frame with correct address.
+ */
+ rt_dest->rt_flags = IEEE80211_MESHRT_FLAGS_PROXY |
+ IEEE80211_MESHRT_FLAGS_VALID;
+ rt_dest->rt_ext_seq = 1; /* random value */
+ IEEE80211_ADDR_COPY(rt_dest->rt_mesh_gate, rt_gate->rt_dest);
+ IEEE80211_ADDR_COPY(rt_dest->rt_nexthop, rt_gate->rt_nexthop);
+ rt_dest->rt_metric = rt_gate->rt_metric;
+ rt_dest->rt_nhops = rt_gate->rt_nhops;
+ ieee80211_mesh_rt_update(rt_dest, ms->ms_ppath->mpp_inact);
+ MESH_RT_UNLOCK(ms);
+ /* XXX: lock?? */
+ mcopy = m_dup(m, M_NOWAIT);
+ for (; mcopy != NULL; mcopy = next) {
+ next = mcopy->m_nextpkt;
+ mcopy->m_nextpkt = NULL;
+ IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_HWMP,
+ rt_dest->rt_dest,
+ "flush queued frame %p len %d", mcopy,
+ mcopy->m_pkthdr.len);
+ mesh_transmit_to_gate(vap, mcopy, rt_gate);
+ }
+ MESH_RT_LOCK(ms);
+ }
+ rt_dest->rt_flags = 0; /* Mark invalid */
+ m_freem(m);
+ MESH_RT_UNLOCK(ms);
+}
+
/*
* Forward the specified frame.
* Decrement the TTL and set TA to our MAC address.
@@ -975,7 +1294,7 @@ mesh_forward(struct ieee80211vap *vap, struct mbuf *m,
ni = ieee80211_ref_node(vap->iv_bss);
mcopy->m_flags |= M_MCAST;
} else {
- ni = mesh_find_txnode(vap, whcopy->i_addr3);
+ ni = ieee80211_mesh_find_txnode(vap, whcopy->i_addr3);
if (ni == NULL) {
/*
* [Optional] any of the following three actions:
@@ -1235,6 +1554,9 @@ mesh_recv_indiv_data_to_me(struct ieee80211vap *vap, struct mbuf *m,
* All other cases: forward of MSDUs from the MBSS to DS indiv.
* addressed according to 13.11.3.2.
*/
+ IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_OUTPUT, qwh->i_addr2,
+ "forward frame to DS, SA(%6D) DA(%6D)",
+ mc10->mc_addr6, ":", mc10->mc_addr5, ":");
}
return (0); /* process locally */
}
@@ -1696,7 +2018,6 @@ mesh_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, int subtype,
}
/*
* Automatically peer with discovered nodes if possible.
- * XXX backoff on repeated failure
*/
if (ni != vap->iv_bss &&
(ms->ms_flags & IEEE80211_MESHFLAGS_AP)) {
@@ -1705,6 +2026,10 @@ mesh_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, int subtype,
{
uint16_t args[1];
+ /* Wait for backoff callout to reset counter */
+ if (ni->ni_mlhcnt >= ieee80211_mesh_maxholding)
+ return;
+
ni->ni_mlpid = mesh_generateid(vap);
if (ni->ni_mlpid == 0)
return;
@@ -2283,19 +2608,177 @@ mesh_recv_action_meshlmetric(struct ieee80211_node *ni,
return 0;
}
+/*
+ * Parse meshgate action ie's for GANN frames.
+ * Returns -1 if parsing fails, otherwise 0.
+ */
+static int
+mesh_parse_meshgate_action(struct ieee80211_node *ni,
+ const struct ieee80211_frame *wh, /* XXX for VERIFY_LENGTH */
+ struct ieee80211_meshgann_ie *ie, const uint8_t *frm, const uint8_t *efrm)
+{
+ struct ieee80211vap *vap = ni->ni_vap;
+ const struct ieee80211_meshgann_ie *gannie;
+
+ while (efrm - frm > 1) {
+ IEEE80211_VERIFY_LENGTH(efrm - frm, frm[1] + 2, return -1);
+ switch (*frm) {
+ case IEEE80211_ELEMID_MESHGANN:
+ gannie = (const struct ieee80211_meshgann_ie *) frm;
+ memset(ie, 0, sizeof(ie));
+ ie->gann_ie = gannie->gann_ie;
+ ie->gann_len = gannie->gann_len;
+ ie->gann_flags = gannie->gann_flags;
+ ie->gann_hopcount = gannie->gann_hopcount;
+ ie->gann_ttl = gannie->gann_ttl;
+ IEEE80211_ADDR_COPY(ie->gann_addr, gannie->gann_addr);
+ ie->gann_seq = LE_READ_4(&gannie->gann_seq);
+ ie->gann_interval = LE_READ_2(&gannie->gann_interval);
+ break;
+ }
+ frm += frm[1] + 2;
+ }
+
+ return 0;
+}
+
+/*
+ * Mesh Gate Announcement handling.
+ */
static int
-mesh_send_action(struct ieee80211_node *ni, struct mbuf *m)
+mesh_recv_action_meshgate(struct ieee80211_node *ni,
+ const struct ieee80211_frame *wh,
+ const uint8_t *frm, const uint8_t *efrm)
{
+ struct ieee80211vap *vap = ni->ni_vap;
+ struct ieee80211_mesh_state *ms = vap->iv_mesh;
+ struct ieee80211_mesh_gate_route *gr, *next;
+ struct ieee80211_mesh_route *rt_gate;
+ struct ieee80211_meshgann_ie pgann;
+ struct ieee80211_meshgann_ie ie;
+ int found = 0;
+
+ /* +2 for action + code */
+ if (mesh_parse_meshgate_action(ni, wh, &ie, frm+2, efrm) != 0) {
+ IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_MESH,
+ ni->ni_macaddr, NULL, "%s",
+ "GANN parsing failed");
+ vap->iv_stats.is_rx_mgtdiscard++;
+ return (0);
+ }
+
+ if (IEEE80211_ADDR_EQ(vap->iv_myaddr, ie.gann_addr))
+ return 0;
+
+ IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, ni->ni_macaddr,
+ "received GANN, meshgate: %6D (seq %u)", ie.gann_addr, ":",
+ ie.gann_seq);
+
+ if (ms == NULL)
+ return (0);
+ MESH_RT_LOCK(ms);
+ TAILQ_FOREACH_SAFE(gr, &ms->ms_known_gates, gr_next, next) {
+ if (!IEEE80211_ADDR_EQ(gr->gr_addr, ie.gann_addr))
+ continue;
+ if (ie.gann_seq <= gr->gr_lastseq) {
+ IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_MESH,
+ ni->ni_macaddr, NULL,
+ "GANN old seqno %u <= %u",
+ ie.gann_seq, gr->gr_lastseq);
+ MESH_RT_UNLOCK(ms);
+ return (0);
+ }
+ /* corresponding mesh gate found & GANN accepted */
+ found = 1;
+ break;
+
+ }
+ if (found == 0) {
+ /* this GANN is from a new mesh Gate add it to known table. */
+ IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, ie.gann_addr,
+ "stored new GANN information, seq %u.", ie.gann_seq);
+ gr = malloc(ALIGN(sizeof(struct ieee80211_mesh_gate_route)),
+ M_80211_MESH_GT_RT, M_NOWAIT | M_ZERO);
+ IEEE80211_ADDR_COPY(gr->gr_addr, ie.gann_addr);
+ TAILQ_INSERT_TAIL(&ms->ms_known_gates, gr, gr_next);
+ }
+ gr->gr_lastseq = ie.gann_seq;
+
+ /* check if we have a path to this gate */
+ rt_gate = mesh_rt_find_locked(ms, gr->gr_addr);
+ if (rt_gate != NULL &&
+ rt_gate->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) {
+ gr->gr_route = rt_gate;
+ rt_gate->rt_flags |= IEEE80211_MESHRT_FLAGS_GATE;
+ }
+
+ MESH_RT_UNLOCK(ms);
+
+ /* popagate only if decremented ttl >= 1 && forwarding is enabled */
+ if ((ie.gann_ttl - 1) < 1 && !(ms->ms_flags & IEEE80211_MESHFLAGS_FWD))
+ return 0;
+ pgann.gann_flags = ie.gann_flags; /* Reserved */
+ pgann.gann_hopcount = ie.gann_hopcount + 1;
+ pgann.gann_ttl = ie.gann_ttl - 1;
+ IEEE80211_ADDR_COPY(pgann.gann_addr, ie.gann_addr);
+ pgann.gann_seq = ie.gann_seq;
+ pgann.gann_interval = ie.gann_interval;
+
+ IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, ie.gann_addr,
+ "%s", "propagate GANN");
+
+ ieee80211_send_action(vap->iv_bss, IEEE80211_ACTION_CAT_MESH,
+ IEEE80211_ACTION_MESH_GANN, &pgann);
+
+ return 0;
+}
+
+static int
+mesh_send_action(struct ieee80211_node *ni,
+ const uint8_t sa[IEEE80211_ADDR_LEN],
+ const uint8_t da[IEEE80211_ADDR_LEN],
+ struct mbuf *m)
+{
+ struct ieee80211vap *vap = ni->ni_vap;
+ struct ieee80211com *ic = ni->ni_ic;
struct ieee80211_bpf_params params;
+ struct ieee80211_frame *wh;
+
+ KASSERT(ni != NULL, ("null node"));
+
+ if (vap->iv_state == IEEE80211_S_CAC) {
+ IEEE80211_NOTE(vap, IEEE80211_MSG_OUTPUT, ni,
+ "block %s frame in CAC state", "Mesh action");
+ vap->iv_stats.is_tx_badstate++;
+ ieee80211_free_node(ni);
+ m_freem(m);
+ return EIO; /* XXX */
+ }
+
+ M_PREPEND(m, sizeof(struct ieee80211_frame), M_DONTWAIT);
+ if (m == NULL) {
+ ieee80211_free_node(ni);
+ return ENOMEM;
+ }
+
+ wh = mtod(m, struct ieee80211_frame *);
+ ieee80211_send_setup(ni, m,
+ IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_ACTION,
+ IEEE80211_NONQOS_TID, sa, da, sa);
+ m->m_flags |= M_ENCAP; /* mark encapsulated */
memset(&params, 0, sizeof(params));
params.ibp_pri = WME_AC_VO;
params.ibp_rate0 = ni->ni_txparms->mgmtrate;
- /* XXX ucast/mcast */
- params.ibp_try0 = ni->ni_txparms->maxretry;
+ if (IEEE80211_IS_MULTICAST(da))
+ params.ibp_try0 = 1;
+ else
+ params.ibp_try0 = ni->ni_txparms->maxretry;
params.ibp_power = ni->ni_txpower;
- return ieee80211_mgmt_output(ni, m, IEEE80211_FC0_SUBTYPE_ACTION,
- &params);
+
+ IEEE80211_NODE_STAT(ni, tx_mgmt);
+
+ return ic->ic_raw_xmit(ni, m, &params);
}
#define ADDSHORT(frm, v) do { \
@@ -2363,7 +2846,7 @@ mesh_send_action_meshpeering_open(struct ieee80211_node *ni,
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);
+ return mesh_send_action(ni, vap->iv_myaddr, ni->ni_macaddr, m);
} else {
vap->iv_stats.is_tx_nobuf++;
ieee80211_free_node(ni);
@@ -2431,7 +2914,7 @@ mesh_send_action_meshpeering_confirm(struct ieee80211_node *ni,
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);
+ return mesh_send_action(ni, vap->iv_myaddr, ni->ni_macaddr, m);
} else {
vap->iv_stats.is_tx_nobuf++;
ieee80211_free_node(ni);
@@ -2480,7 +2963,7 @@ mesh_send_action_meshpeering_close(struct ieee80211_node *ni,
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);
+ return mesh_send_action(ni, vap->iv_myaddr, ni->ni_macaddr, m);
} else {
vap->iv_stats.is_tx_nobuf++;
ieee80211_free_node(ni);
@@ -2528,7 +3011,46 @@ mesh_send_action_meshlmetric(struct ieee80211_node *ni,
frm = ieee80211_add_meshlmetric(frm,
ie->lm_flags, ie->lm_metric);
m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *);
- return mesh_send_action(ni, m);
+ return mesh_send_action(ni, vap->iv_myaddr, ni->ni_macaddr, m);
+ } else {
+ vap->iv_stats.is_tx_nobuf++;
+ ieee80211_free_node(ni);
+ return ENOMEM;
+ }
+}
+
+static int
+mesh_send_action_meshgate(struct ieee80211_node *ni,
+ int category, int action, void *arg0)
+{
+ struct ieee80211vap *vap = ni->ni_vap;
+ struct ieee80211com *ic = ni->ni_ic;
+ struct ieee80211_meshgann_ie *ie = arg0;
+ struct mbuf *m;
+ uint8_t *frm;
+
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE,
+ "ieee80211_ref_node (%s:%u) %p<%s> refcnt %d\n", __func__, __LINE__,
+ ni, ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni)+1);
+ ieee80211_ref_node(ni);
+
+ m = ieee80211_getmgtframe(&frm,
+ ic->ic_headroom + sizeof(struct ieee80211_frame),
+ sizeof(uint16_t) + /* action+category */
+ IEEE80211_MESHGANN_BASE_SZ
+ );
+ if (m != NULL) {
+ /*
+ * mesh link metric
+ * [1] category
+ * [1] action
+ * [tlv] mesh gate annoucement
+ */
+ *frm++ = category;
+ *frm++ = action;
+ frm = ieee80211_add_meshgate(frm, ie);
+ m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *);
+ return mesh_send_action(ni, vap->iv_myaddr, broadcastaddr, m);
} else {
vap->iv_stats.is_tx_nobuf++;
ieee80211_free_node(ni);
@@ -2578,6 +3100,15 @@ mesh_peer_timeout_stop(struct ieee80211_node *ni)
callout_drain(&ni->ni_mltimer);
}
+static void
+mesh_peer_backoff_cb(void *arg)
+{
+ struct ieee80211_node *ni = (struct ieee80211_node *)arg;
+
+ /* After backoff timeout, try to peer automatically again. */
+ ni->ni_mlhcnt = 0;
+}
+
/*
* Mesh Peer Link Management FSM timeout handling.
*/
@@ -2625,6 +3156,11 @@ mesh_peer_timeout_cb(void *arg)
mesh_peer_timeout_setup(ni);
break;
case IEEE80211_NODE_MESH_HOLDING:
+ ni->ni_mlhcnt++;
+ if (ni->ni_mlhcnt >= ieee80211_mesh_maxholding)
+ callout_reset(&ni->ni_mlhtimer,
+ ieee80211_mesh_backofftimeout,
+ mesh_peer_backoff_cb, ni);
mesh_linkchange(ni, IEEE80211_NODE_MESH_IDLE);
break;
}
@@ -2878,6 +3414,24 @@ ieee80211_add_meshlmetric(uint8_t *frm, uint8_t flags, uint32_t metric)
ADDWORD(frm, metric);
return frm;
}
+
+/*
+ * Add a Mesh Gate Announcement IE to a frame.
+ */
+uint8_t *
+ieee80211_add_meshgate(uint8_t *frm, struct ieee80211_meshgann_ie *ie)
+{
+ *frm++ = IEEE80211_ELEMID_MESHGANN; /* ie */
+ *frm++ = IEEE80211_MESHGANN_BASE_SZ; /* len */
+ *frm++ = ie->gann_flags;
+ *frm++ = ie->gann_hopcount;
+ *frm++ = ie->gann_ttl;
+ IEEE80211_ADDR_COPY(frm, ie->gann_addr);
+ frm += 6;
+ ADDWORD(frm, ie->gann_seq);
+ ADDSHORT(frm, ie->gann_interval);
+ return frm;
+}
#undef ADDSHORT
#undef ADDWORD
@@ -2889,6 +3443,7 @@ ieee80211_mesh_node_init(struct ieee80211vap *vap, struct ieee80211_node *ni)
{
ni->ni_flags |= IEEE80211_NODE_QOS;
callout_init(&ni->ni_mltimer, CALLOUT_MPSAFE);
+ callout_init(&ni->ni_mlhtimer, CALLOUT_MPSAFE);
}
/*
@@ -2901,6 +3456,7 @@ ieee80211_mesh_node_cleanup(struct ieee80211_node *ni)
struct ieee80211_mesh_state *ms = vap->iv_mesh;
callout_drain(&ni->ni_mltimer);
+ callout_drain(&ni->ni_mlhtimer);
/* NB: short-circuit callbacks after mesh_vdetach */
if (vap->iv_mesh != NULL)
ms->ms_ppath->mpp_peerdown(ni);
@@ -3080,6 +3636,7 @@ mesh_ioctl_set80211(struct ieee80211vap *vap, struct ieee80211req *ireq)
ms->ms_flags |= IEEE80211_MESHFLAGS_FWD;
else
ms->ms_flags &= ~IEEE80211_MESHFLAGS_FWD;
+ mesh_gatemode_setup(vap);
break;
case IEEE80211_IOC_MESH_GATE:
if (ireq->i_val)
diff --git a/sys/net80211/ieee80211_mesh.h b/sys/net80211/ieee80211_mesh.h
index f161012..5dc2b2c 100644
--- a/sys/net80211/ieee80211_mesh.h
+++ b/sys/net80211/ieee80211_mesh.h
@@ -194,14 +194,20 @@ struct ieee80211_meshbeacont_ie {
#endif
/* Gate (GANN) Annoucement */
+/*
+ * NB: these macros used for the length in the IEs does not include 2 bytes
+ * for _ie and _len fields as is defined by the standard.
+ */
+#define IEEE80211_MESHGANN_BASE_SZ (15)
struct ieee80211_meshgann_ie {
- uint8_t pann_ie; /* IEEE80211_ELEMID_MESHGANN */
- uint8_t pann_len;
- uint8_t pann_flags;
- uint8_t pann_hopcount;
- uint8_t pann_ttl;
- uint8_t pann_addr[IEEE80211_ADDR_LEN];
- uint8_t pann_seq; /* PANN Sequence Number */
+ uint8_t gann_ie; /* IEEE80211_ELEMID_MESHGANN */
+ uint8_t gann_len;
+ uint8_t gann_flags;
+ uint8_t gann_hopcount;
+ uint8_t gann_ttl;
+ uint8_t gann_addr[IEEE80211_ADDR_LEN];
+ uint32_t gann_seq; /* GANN Sequence Number */
+ uint16_t gann_interval; /* GANN Interval */
} __packed;
/* Root (MP) Annoucement */
@@ -399,6 +405,7 @@ MALLOC_DECLARE(M_80211_MESH_PREP);
MALLOC_DECLARE(M_80211_MESH_PERR);
MALLOC_DECLARE(M_80211_MESH_RT);
+MALLOC_DECLARE(M_80211_MESH_GT_RT);
/*
* Basic forwarding information:
* o Destination MAC
@@ -423,6 +430,7 @@ struct ieee80211_mesh_route {
#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 */
+#define IEEE80211_MESHRT_FLAGS_GATE 0x08 /* mesh gate entry */
uint32_t rt_lifetime; /* route timeout */
uint32_t rt_lastmseq; /* last seq# seen dest */
uint32_t rt_ext_seq; /* proxy seq number */
@@ -430,6 +438,16 @@ struct ieee80211_mesh_route {
};
#define IEEE80211_MESH_ROUTE_PRIV(rt, cast) ((cast *)rt->rt_priv)
+/*
+ * Stored information about known mesh gates.
+ */
+struct ieee80211_mesh_gate_route {
+ TAILQ_ENTRY(ieee80211_mesh_gate_route) gr_next;
+ uint8_t gr_addr[IEEE80211_ADDR_LEN];
+ uint32_t gr_lastseq;
+ struct ieee80211_mesh_route *gr_route;
+};
+
#define IEEE80211_MESH_PROTO_DSZ 12 /* description size */
/*
* Mesh Path Selection Protocol.
@@ -495,9 +513,13 @@ struct ieee80211_mesh_state {
#define IEEE80211_MESHFLAGS_AP 0x01 /* accept peers */
#define IEEE80211_MESHFLAGS_GATE 0x02 /* mesh gate role */
#define IEEE80211_MESHFLAGS_FWD 0x04 /* forward packets */
+#define IEEE80211_MESHFLAGS_ROOT 0x08 /* configured as root */
uint8_t ms_flags;
struct mtx ms_rt_lock;
struct callout ms_cleantimer;
+ struct callout ms_gatetimer;
+ ieee80211_mesh_seq ms_gateseq;
+ TAILQ_HEAD(, ieee80211_mesh_gate_route) ms_known_gates;
TAILQ_HEAD(, ieee80211_mesh_route) ms_routes;
struct ieee80211_mesh_proto_metric *ms_pmetric;
struct ieee80211_mesh_proto_path *ms_ppath;
@@ -530,6 +552,8 @@ uint8_t * ieee80211_add_meshconf(uint8_t *, struct ieee80211vap *);
uint8_t * ieee80211_add_meshpeer(uint8_t *, uint8_t, uint16_t, uint16_t,
uint16_t);
uint8_t * ieee80211_add_meshlmetric(uint8_t *, uint8_t, uint32_t);
+uint8_t * ieee80211_add_meshgate(uint8_t *,
+ struct ieee80211_meshgann_ie *);
void ieee80211_mesh_node_init(struct ieee80211vap *,
struct ieee80211_node *);
@@ -542,6 +566,14 @@ void ieee80211_mesh_init_neighbor(struct ieee80211_node *,
const struct ieee80211_scanparams *);
void ieee80211_mesh_update_beacon(struct ieee80211vap *,
struct ieee80211_beacon_offsets *);
+struct ieee80211_mesh_gate_route *
+ ieee80211_mesh_mark_gate(struct ieee80211vap *,
+ const uint8_t *, struct ieee80211_mesh_route *);
+void ieee80211_mesh_forward_to_gates(struct ieee80211vap *,
+ struct ieee80211_mesh_route *);
+struct ieee80211_node *
+ ieee80211_mesh_find_txnode(struct ieee80211vap *,
+ const uint8_t [IEEE80211_ADDR_LEN]);
/*
* Return non-zero if proxy operation is enabled.
diff --git a/sys/net80211/ieee80211_node.h b/sys/net80211/ieee80211_node.h
index 48eae2d..bb31136 100644
--- a/sys/net80211/ieee80211_node.h
+++ b/sys/net80211/ieee80211_node.h
@@ -204,6 +204,8 @@ struct ieee80211_node {
struct callout ni_mltimer; /* link mesh timer */
uint8_t ni_mlrcnt; /* link mesh retry counter */
uint8_t ni_mltval; /* link mesh timer value */
+ struct callout ni_mlhtimer; /* link mesh backoff timer */
+ uint8_t ni_mlhcnt; /* link mesh holding counter */
/* 11n state */
uint16_t ni_htcap; /* HT capabilities */
diff --git a/sys/net80211/ieee80211_output.c b/sys/net80211/ieee80211_output.c
index 57925f2..7481488 100644
--- a/sys/net80211/ieee80211_output.c
+++ b/sys/net80211/ieee80211_output.c
@@ -262,6 +262,10 @@ ieee80211_start(struct ifnet *ifp)
m_freem(m);
continue;
}
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT,
+ "forward frame from DS SA(%6D), DA(%6D)\n",
+ eh->ether_shost, ":",
+ eh->ether_dhost, ":");
ieee80211_mesh_proxy_check(vap, eh->ether_shost);
}
ni = ieee80211_mesh_discover(vap, eh->ether_dhost, m);
diff --git a/sys/ofed/drivers/net/mlx4/en_tx.c b/sys/ofed/drivers/net/mlx4/en_tx.c
index e2e13c2..fee7afe 100644
--- a/sys/ofed/drivers/net/mlx4/en_tx.c
+++ b/sys/ofed/drivers/net/mlx4/en_tx.c
@@ -931,22 +931,21 @@ mlx4_en_transmit_locked(struct ifnet *dev, int tx_ind, struct mbuf *m)
}
enqueued = 0;
- if (m == NULL) {
- next = drbr_dequeue(dev, ring->br);
- } else if (drbr_needs_enqueue(dev, ring->br)) {
+ if (m != NULL) {
if ((err = drbr_enqueue(dev, ring->br, m)) != 0)
return (err);
- next = drbr_dequeue(dev, ring->br);
- } else
- next = m;
-
+ }
/* Process the queue */
- while (next != NULL) {
+ while ((next = drbr_peek(ifp, ring->br)) != NULL) {
if ((err = mlx4_en_xmit(dev, tx_ind, &next)) != 0) {
- if (next != NULL)
- err = drbr_enqueue(dev, ring->br, next);
+ if (next == NULL) {
+ drbr_advance(ifp, ring->br);
+ } else {
+ drbr_putback(ifp, ring->br, next);
+ }
break;
}
+ drbr_advance(ifp, ring->br);
enqueued++;
dev->if_obytes += next->m_pkthdr.len;
if (next->m_flags & M_MCAST)
@@ -955,7 +954,6 @@ mlx4_en_transmit_locked(struct ifnet *dev, int tx_ind, struct mbuf *m)
ETHER_BPF_MTAP(dev, next);
if ((dev->if_drv_flags & IFF_DRV_RUNNING) == 0)
break;
- next = drbr_dequeue(dev, ring->br);
}
if (enqueued > 0)
diff --git a/sys/sparc64/include/vmparam.h b/sys/sparc64/include/vmparam.h
index 6b33e0f..a5ed245 100644
--- a/sys/sparc64/include/vmparam.h
+++ b/sys/sparc64/include/vmparam.h
@@ -149,8 +149,8 @@
*
* We define some interesting address constants:
*
- * VM_MIN_ADDRESS and VM_MAX_ADDRESS define the start and of the entire 64 bit
- * address space, mostly just for convenience.
+ * VM_MIN_ADDRESS and VM_MAX_ADDRESS define the start and end of the entire
+ * 64 bit address space, mostly just for convenience.
*
* VM_MIN_DIRECT_ADDRESS and VM_MAX_DIRECT_ADDRESS define the start and end
* of the direct mapped region. This maps virtual addresses to physical
diff --git a/sys/sys/buf_ring.h b/sys/sys/buf_ring.h
index b660d9b..b1ccaec 100644
--- a/sys/sys/buf_ring.h
+++ b/sys/sys/buf_ring.h
@@ -208,6 +208,54 @@ buf_ring_dequeue_sc(struct buf_ring *br)
}
/*
+ * single-consumer advance after a peek
+ * use where it is protected by a lock
+ * e.g. a network driver's tx queue lock
+ */
+static __inline void
+buf_ring_advance_sc(struct buf_ring *br)
+{
+ uint32_t cons_head, cons_next;
+ uint32_t prod_tail;
+
+ cons_head = br->br_cons_head;
+ prod_tail = br->br_prod_tail;
+
+ cons_next = (cons_head + 1) & br->br_cons_mask;
+ if (cons_head == prod_tail)
+ return;
+ br->br_cons_head = cons_next;
+#ifdef DEBUG_BUFRING
+ br->br_ring[cons_head] = NULL;
+#endif
+ br->br_cons_tail = cons_next;
+}
+
+/*
+ * Used to return a buffer (most likely already there)
+ * to the top od the ring. The caller should *not*
+ * have used any dequeue to pull it out of the ring
+ * but instead should have used the peek() function.
+ * This is normally used where the transmit queue
+ * of a driver is full, and an mubf must be returned.
+ * Most likely whats in the ring-buffer is what
+ * is being put back (since it was not removed), but
+ * sometimes the lower transmit function may have
+ * done a pullup or other function that will have
+ * changed it. As an optimzation we always put it
+ * back (since jhb says the store is probably cheaper),
+ * if we have to do a multi-queue version we will need
+ * the compare and an atomic.
+ */
+static __inline void
+buf_ring_putback_sc(struct buf_ring *br, void *new)
+{
+ KASSERT(br->br_cons_head != br->br_prod_tail,
+ ("Buf-Ring has none in putback")) ;
+ br->br_ring[br->br_cons_head] = new;
+}
+
+/*
* return a pointer to the first entry in the ring
* without modifying it, or NULL if the ring is empty
* race-prone if not protected by a lock
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index 78af5c0..ade2864 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -636,6 +636,7 @@ struct proc {
#define P_INMEM 0x10000000 /* Loaded into memory. */
#define P_SWAPPINGOUT 0x20000000 /* Process is being swapped out. */
#define P_SWAPPINGIN 0x40000000 /* Process is being swapped in. */
+#define P_PPTRACE 0x80000000 /* PT_TRACEME by vforked child. */
#define P_STOPPED (P_STOPPED_SIG|P_STOPPED_SINGLE|P_STOPPED_TRACE)
#define P_SHOULDSTOP(p) ((p)->p_flag & P_STOPPED)
diff --git a/sys/ufs/ufs/inode.h b/sys/ufs/ufs/inode.h
index 59b170c..6416632 100644
--- a/sys/ufs/ufs/inode.h
+++ b/sys/ufs/ufs/inode.h
@@ -151,10 +151,6 @@ struct inode {
(ip)->i_din2->d##field = (val); \
} while (0)
-#define MAXSYMLINKLEN(ip) \
- ((ip)->i_ump->um_fstype == UFS1) ? \
- ((NDADDR + NIADDR) * sizeof(ufs1_daddr_t)) : \
- ((NDADDR + NIADDR) * sizeof(ufs2_daddr_t))
#define SHORTLINK(ip) \
(((ip)->i_ump->um_fstype == UFS1) ? \
(caddr_t)(ip)->i_din1->di_db : (caddr_t)(ip)->i_din2->di_db)
diff --git a/usr.bin/newgrp/newgrp.1 b/usr.bin/newgrp/newgrp.1
index 44ab9fd..4635584 100644
--- a/usr.bin/newgrp/newgrp.1
+++ b/usr.bin/newgrp/newgrp.1
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd May 23, 2002
+.Dd February 8, 2013
.Dt NEWGRP 1
.Os
.Sh NAME
@@ -90,6 +90,15 @@ A
utility appeared in
.At v6 .
.Sh BUGS
+For security reasons, the
+.Nm
+utility is normally installed without the setuid bit.
+To enable it, run the following command:
+.Bd -literal -offset indent
+chmod u+s /usr/bin/newgrp
+.Ed
+.Pp
Group passwords are inherently insecure as there is no way to stop
-users obtaining the crypted passwords from the group database.
+users obtaining the password hash from the group database.
Their use is discouraged.
+Instead, users should simply be added to the necessary groups.
diff --git a/usr.bin/newgrp/newgrp.c b/usr.bin/newgrp/newgrp.c
index b3f6103..9b3972e 100644
--- a/usr.bin/newgrp/newgrp.c
+++ b/usr.bin/newgrp/newgrp.c
@@ -73,7 +73,8 @@ main(int argc, char *argv[])
{
int ch, login;
- euid = geteuid();
+ if ((euid = geteuid()) != 0)
+ warnx("need root permissions to function properly, check setuid bit");
if (seteuid(getuid()) < 0)
err(1, "seteuid");
diff --git a/usr.bin/patch/util.c b/usr.bin/patch/util.c
index 3895b2c..28a3cb0 100644
--- a/usr.bin/patch/util.c
+++ b/usr.bin/patch/util.c
@@ -412,7 +412,7 @@ checked_in(char *file)
void
version(void)
{
- fprintf(stderr, "patch (BSD patch) 2.0-FreeBSD\n");
+ fprintf(stderr, "patch 2.0-12u8 FreeBSD\n");
my_exit(EXIT_SUCCESS);
}
diff --git a/usr.sbin/bsdconfig/Makefile b/usr.sbin/bsdconfig/Makefile
index 7576194..4faad0b 100644
--- a/usr.sbin/bsdconfig/Makefile
+++ b/usr.sbin/bsdconfig/Makefile
@@ -1,7 +1,5 @@
# $FreeBSD$
-NO_OBJ=
-
SUBDIR= console \
diskmgmt \
docsinstall \
diff --git a/usr.sbin/sysrc/Makefile b/usr.sbin/sysrc/Makefile
index 38c52ee..ca3dc56 100644
--- a/usr.sbin/sysrc/Makefile
+++ b/usr.sbin/sysrc/Makefile
@@ -1,7 +1,5 @@
# $FreeBSD$
-NO_OBJ=
-
SCRIPTS= sysrc
MAN= sysrc.8
OpenPOWER on IntegriCloud