Re: make tcpdump show 11n mode correctly

2016-12-17 Thread Stefan Sperling
Anybody?

Did I write too much of a wall of text to explain the diff?
In that case, just read the diff. It should make sense.

On Sun, Dec 11, 2016 at 04:38:44PM +0100, Stefan Sperling wrote:
> This diff makes 'tcpdump -i iwn0 -y IEEE802_11_RADIO' show the
> correct mode for a channel in 11n mode.
> Before:
>  
> After:
>  
> 
> Unfortunately this requires a kernel tweak because the kernel must
> be more careful about the channel flags it passes to userland.
> 
> Channels exist in the 11b/g (2GHz) and 11a (5GHz) ranges.
> So net80211 has a "mode" concept, where a given mode is available
> if supported channels exist in a particular range. And there is the
> default "auto" mode which picks one of the other available modes.
> (This may not be the best design but it is how it was designed
> historically. Changing this is not in my radar.)
> 
> The HT-channel flag is set to indicate whether a channel may be used
> in 11n mode. In practice this is just the superset of all channels
> supported by the device. When 11n support was introduced it was easier to
> fold the new 11n mode into the existing code with a flag like this, and
> avoid letting 11n mode be a special case which works against this design.
> 
> And this HT-channel flag is set regardless of whether we're currently in
> 11n mode because we need this flag to enter 11n mode from another mode.
> A mode which has no channels available to it is not available.
> So the kernel needs this flag to be set on all channels at all times
> if the driver supports 11n.
> 
> Now, we copy this flag out to userspace even in non-11n modes.
> If the kernel instead omits the HT-channel flag from the userspace copy if
> the current mode is not 11n, then tcpdump can inspect this flag to detect
> whether the channel is in fact an "11n" channel and print the mode correctly.
> 
> In the end, this is just a cosmetic fix. If this is too much code
> churn and quirks for too little gain, I am happy to drop this diff.
> 
> Index: sys/dev/pci/if_iwm.c
> ===
> RCS file: /cvs/src/sys/dev/pci/if_iwm.c,v
> retrieving revision 1.154
> diff -u -p -r1.154 if_iwm.c
> --- sys/dev/pci/if_iwm.c  10 Dec 2016 19:03:53 -  1.154
> +++ sys/dev/pci/if_iwm.c  11 Dec 2016 14:54:58 -
> @@ -3339,14 +3339,17 @@ iwm_rx_rx_mpdu(struct iwm_softc *sc, str
>   if (sc->sc_drvbpf != NULL) {
>   struct mbuf mb;
>   struct iwm_rx_radiotap_header *tap = &sc->sc_rxtap;
> + uint16_t chan_flags;
>  
>   tap->wr_flags = 0;
>   if (phy_info->phy_flags & htole16(IWM_PHY_INFO_FLAG_SHPREAMBLE))
>   tap->wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
>   tap->wr_chan_freq =
>   htole16(ic->ic_channels[phy_info->channel].ic_freq);
> - tap->wr_chan_flags =
> - htole16(ic->ic_channels[phy_info->channel].ic_flags);
> + chan_flags = ic->ic_channels[phy_info->channel].ic_flags;
> + if (ic->ic_curmode != IEEE80211_MODE_11N)
> + chan_flags &= ~IEEE80211_CHAN_HT;
> + tap->wr_chan_flags = htole16(chan_flags);
>   tap->wr_dbm_antsignal = (int8_t)rssi;
>   tap->wr_dbm_antnoise = (int8_t)sc->sc_noise;
>   tap->wr_tsft = phy_info->system_timestamp;
> @@ -3991,10 +3994,14 @@ iwm_tx(struct iwm_softc *sc, struct mbuf
>   if (sc->sc_drvbpf != NULL) {
>   struct mbuf mb;
>   struct iwm_tx_radiotap_header *tap = &sc->sc_txtap;
> + uint16_t chan_flags;
>  
>   tap->wt_flags = 0;
>   tap->wt_chan_freq = htole16(ni->ni_chan->ic_freq);
> - tap->wt_chan_flags = htole16(ni->ni_chan->ic_flags);
> + chan_flags = ni->ni_chan->ic_flags;
> + if (ic->ic_curmode != IEEE80211_MODE_11N)
> + chan_flags &= ~IEEE80211_CHAN_HT;
> + tap->wt_chan_flags = htole16(chan_flags);
>   if ((ni->ni_flags & IEEE80211_NODE_HT) &&
>   !IEEE80211_IS_MULTICAST(wh->i_addr1) &&
>   type == IEEE80211_FC0_TYPE_DATA &&
> Index: sys/dev/pci/if_iwn.c
> ===
> RCS file: /cvs/src/sys/dev/pci/if_iwn.c,v
> retrieving revision 1.178
> diff -u -p -r1.178 if_iwn.c
> --- sys/dev/pci/if_iwn.c  10 Dec 2016 13:22:07 -  1.178
> +++ sys/dev/pci/if_iwn.c  11 Dec 2016 14:54:25 -
> @@ -2130,14 +2130,17 @@ iwn_rx_done(struct iwn_softc *sc, struct
>   if (sc->sc_drvbpf != NULL) {
>   struct mbuf mb;
>   struct iwn_rx_radiotap_header *tap = &sc->sc_rxtap;
> + uint16_t chan_flags;
>  
>   tap->wr_flags = 0;
>   if (stat->flags & htole16(IWN_STAT_FLAG_SHPREAMBLE))
>   tap->wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
>   tap->wr_chan_freq =
> 

Re: kernel diagnostic assertion "ifa == rt->rt_ifa", rt_ifa_addlocal

2016-12-17 Thread Martin Pieuchot
On 17/12/16(Sat) 07:52, Stefan Sperling wrote:
> On Sat, Dec 17, 2016 at 02:33:37AM +0100, Alexander Bluhm wrote:
> > Hi,
> > 
> > If rt_ifa_addlocal() in in_ifinit() fails, the address has been
> > added to the interface address list, but the local route is missing.
> > This inconsistency can result in a panic later.
> > 
> > panic: kernel diagnostic assertion "ifa == rt->rt_ifa" failed: file 
> > "/crypt/home/bluhm/openbsd/cvs/src/sys/netinet/if_ether.c", line 206
> > 
> > I have seen this crash in production on a 5.9 system and could
> > reproduce it on -current by inducing an error in rt_ifa_addlocal().
> > 
> > So in case of an error, remove the interface address to get a
> > consistent state again.
> > 
> > ok?

Haha, I have a similar diff in my tree!  I couldn't find a way to make
rt_ifa_addlocal() fail, but I agree this is needed.  ok mpi@

> The little dance with an aditional error variable is a bit confusing.
> It would be nice to avoid the extra variable. But off-hand I could not
> find a simpler diff which keeps the semantics of re-adding the original
> address if the ioctl errors. So your approach seems fine.

The proper way to simplify this mess is to always call in_ifinit() with
newifaddr = 1.  But it is the kind of work nobody want to spend her time
on.



Re: BFD: route get and route monitor

2016-12-17 Thread Peter Hessler
On 2016 Sep 30 (Fri) at 10:16:19 +0200 (+0200), Peter Hessler wrote:
:This diff makes route get and route monitor work.  sockaddr_bfd is so we
:can play like the other RTAX_* indexes in rti_info of route messages.
:
:OK?

Updated output, requested by Theo.  A normal get will show just the bfd
state, use "-bfd" to get all of the information.

OK?

$ route -n get 203.0.113.9
   route to: 203.0.113.9
destination: 203.0.113.9
   mask: 255.255.255.255
  interface: em1
 if address: 203.0.113.1
   priority: 4 (connected)
  flags: 
BFD: async state up remote up
 use   mtuexpire
   83924 0   133 
sockaddrs: 

$ route -n get 203.0.113.9 -bfd
   route to: 203.0.113.9
destination: 203.0.113.9
   mask: 255.255.255.255
  interface: em1
 if address: 203.0.113.1
   priority: 4 (connected)
  flags: 
BFD: async state up remote up laststate down error 0
 diag none remote neighbor-down
 discr 186919089 remote 55
 uptime 05d 2h07m29s
 mintx 100 minrx 100 minecho 0 multiplier 3
 use   mtuexpire
   83923 0   229 
sockaddrs: 


Index: sbin/route/Makefile
===
RCS file: /cvs/openbsd/src/sbin/route/Makefile,v
retrieving revision 1.13
diff -u -p -u -p -r1.13 Makefile
--- sbin/route/Makefile 19 Jul 2013 14:41:46 -  1.13
+++ sbin/route/Makefile 17 Dec 2016 12:47:35 -
@@ -4,7 +4,7 @@ PROG=   route
 MAN=   route.8
 SRCS=  route.c show.c
 
-CFLAGS+=   -Wall
+CFLAGS+=   -Wall -DBFD
 
 route.o .depend lint tags: keywords.h
 
Index: sbin/route/route.c
===
RCS file: /cvs/openbsd/src/sbin/route/route.c,v
retrieving revision 1.193
diff -u -p -u -p -r1.193 route.c
--- sbin/route/route.c  13 Dec 2016 08:40:54 -  1.193
+++ sbin/route/route.c  17 Dec 2016 12:47:35 -
@@ -100,6 +100,7 @@ const char *bfd_state(unsigned int);
 const char *bfd_diag(unsigned int);
 const char *bfd_calc_uptime(time_t);
 voidprint_bfdmsg(struct rt_msghdr *);
+voidprint_sabfd(struct sockaddr_bfd *, int);
 #endif
 const char *get_linkstate(int, int);
 voidprint_rtmsg(struct rt_msghdr *, int);
@@ -1443,6 +1444,9 @@ print_getmsg(struct rt_msghdr *rtm, int 
struct sockaddr *dst = NULL, *gate = NULL, *mask = NULL, *ifa = NULL;
struct sockaddr_dl *ifp = NULL;
struct sockaddr_rtlabel *sa_rl = NULL;
+#ifdef BFD
+   struct sockaddr_bfd *sa_bfd = NULL;
+#endif
struct sockaddr *mpls = NULL;
struct sockaddr *sa;
char *cp;
@@ -1491,6 +1495,11 @@ print_getmsg(struct rt_msghdr *rtm, int 
case RTA_LABEL:
sa_rl = (struct sockaddr_rtlabel *)sa;
break;
+#ifdef BFD
+   case RTA_BFD:
+   sa_bfd = (struct sockaddr_bfd *)sa;
+   break;
+#endif
}
ADVANCE(cp, sa);
}
@@ -1523,6 +1532,10 @@ print_getmsg(struct rt_msghdr *rtm, int 
printf("\n");
if (sa_rl != NULL)
printf("  label: %s\n", sa_rl->sr_label);
+#ifdef BFD
+   if (sa_bfd)
+   print_sabfd(sa_bfd, rtm->rtm_fmask);
+#endif
 
 #define lock(f)((rtm->rtm_rmx.rmx_locks & __CONCAT(RTV_,f)) ? 'L' : ' 
')
relative_expire = rtm->rtm_rmx.rmx_expire ?
@@ -1625,12 +1638,21 @@ void
 print_bfdmsg(struct rt_msghdr *rtm)
 {
struct bfd_msghdr *bfdm = (struct bfd_msghdr *)rtm;
+
+   printf("\n");
+   print_sabfd(&bfdm->bm_sa, rtm->rtm_fmask);
+   pmsg_addrs(((char *)rtm + rtm->rtm_hdrlen), rtm->rtm_addrs);
+}
+
+void
+print_sabfd(struct sockaddr_bfd *sa_bfd, int fmask)
+{
struct timeval tv;
 
gettimeofday(&tv, NULL);
 
-   printf(" mode ");
-   switch (bfdm->bm_mode) {
+   printf("BFD: ");
+   switch (sa_bfd->bs_mode) {
case BFD_MODE_ASYNC:
printf("async");
break;
@@ -1638,27 +1660,36 @@ print_bfdmsg(struct rt_msghdr *rtm)
printf("demand");
break;
default:
-   printf("unknown %u", bfdm->bm_mode);
+   printf("unknown %u", sa_bfd->bs_mode);
break;
}
-   printf(" state %s", bfd_state(bfdm->bm_state));
-   printf(" remotestate %s", bfd_state(bfdm->bm_remotestate));
-   printf(" laststate %s", bfd_state(bfdm->bm_laststate));
-
-   printf(" error %d", bfdm->bm_error);
-   printf(" localdiscr %u", bfdm->bm_localdiscr);
-   printf(" remotediscr %u", bfdm->bm_remotediscr);
-   printf(" localdiag %s", bfd_diag(bfdm->bm_localdiag));
-   printf(" remotediag %s", bfd_diag(bfdm->bm_remotediag));
-   printf(" uptime %s", bfd_calc_uptime(tv.t