Re: net80211: use BSS load information when choosing access point

2021-11-09 Thread Sergey Ryazanov
Hello Stefan,

sorry for the late reply, find my comments below.

On Wed, Nov 3, 2021 at 4:47 PM Stefan Sperling  wrote:
> On Wed, Nov 03, 2021 at 04:03:08PM +0300, Sergey Ryazanov wrote:
>> This topic was discussed a couple of weeks ago on the hostapd mailing
>> list (http://lists.infradead.org/pipermail/hostap/2021-October/039961.html).
>> And Jouni Malinen provide a few concerns about switching to the QBSS
>> load IE usage. I would like to quote him:
>>
>>> I would also point out that at least the last time I did some testing
>>> between vendor implementations, the reported values were completely
>>> different between two APs on the same channel in more or less the same
>>> location in the test setup.. In other words, I would not place much, if
>>> any, trust in this value being something that could be compared between
>>> two different APs. The only thing that seemed to be more or less
>>> comparable was the values from the same AP device in a sense that the
>>> channel load value increased when there was more traffic on the
>>> channel..
>>
>> So I do not think that the complete switching to the BSS load metric
>> is a good idea. But utilizing the AP assistance in the BSS selection
>> procedure sounds nice.
>
> My patch ignores RSSI on purpose in case BSS load is advertised precisely
> because we need to figure out whether "channel load" is indicated reliably.
> The standard doesn't really go into much detail about how to decide whether
> a channel is "busy". It suggests that either virtual or physical carrier
> sense could be used. I guess just letting any faint but valid wifi signal
> block the channel would be a bad idea. So vendors may need to use some
> threshold to decide whether a given signal is actually keeping the channel
> busy in the vicinity of the AP. As with RSSI, measurements of such physical
> quantities could differ between any two given APs and between moments in
> time for a single AP.
>
> If channel load is not a reliable indicator I would hope vendors are at
> least able to reliably count and report the number of associated stations?

The number of associated stations is a comparable metric. But it
provides no information about the channel utilization. Consider two
APs: one with 10 associated but idle smartphones and one with two
laptops that receive a 20 mbit/s video stream each. It is better to
connect to the first AP with the idle channel, but the stations number
metric directs us to quite loaded AP.

--
Sergey



Re: net80211: use BSS load information when choosing access point

2021-11-03 Thread Sergey Ryazanov
Hello Stefan,

On Sun, Oct 31, 2021 at 9:25 PM Stefan Sperling  wrote:
> Some access points advertise BSS load information in beacons in
> order to help clients make informed roaming decisions.
>
> BSS load information includes the number of associated stations,
> the channel utilization (this takes other networks on the same
> channel into account), and current admission capacity (interesting
> for clients which use QoS, which we do not).
>
> We currently ignore BSS load information and only use RSSI to tell APs
> apart. With this patch we store bss load information for APs during
> scans if available, and take it into account when chosing an access point.
>
> Unfortunately, I do not have a suitable AP available to test with.
> tcpdump can be used to check whether an access point supports this
> feature. Run this command while associated to the access point:
>  tcpdump -n -i iwm0 -y IEEE802_11_RADIO -s 4096 -v
>
> If the AP reports BSS load information you should see something like
> this among the information printed by tcpdump:
>   64 stations, 100% utilization, admission capacity 0us/s
>
> It would help to get this patch tested in an environment where access
> points advertise BSS load information, with a roaming test between
> different access points.
> I wrote down information about how roaming can be tested here:
> https://marc.info/?l=openbsd-tech=163329420019842=2

This topic was discussed a couple of weeks ago on the hostapd mailing
list (http://lists.infradead.org/pipermail/hostap/2021-October/039961.html).
And Jouni Malinen provide a few concerns about switching to the QBSS
load IE usage. I would like to quote him:

> I would also point out that at least the last time I did some testing
> between vendor implementations, the reported values were completely
> different between two APs on the same channel in more or less the same
> location in the test setup.. In other words, I would not place much, if
> any, trust in this value being something that could be compared between
> two different APs. The only thing that seemed to be more or less
> comparable was the values from the same AP device in a sense that the
> channel load value increased when there was more traffic on the
> channel..

So I do not think that the complete switching to the BSS load metric
is a good idea. But utilizing the AP assistance in the BSS selection
procedure sounds nice.

-- 
Sergey



Re: [PATCH] pipex(4): rework PPP input

2020-05-26 Thread Sergey Ryazanov
On Wed, May 27, 2020 at 2:12 AM Vitaliy Makkoveev
 wrote:
> > On 27 May 2020, at 01:29, Sergey Ryazanov  wrote:
> > On Tue, May 26, 2020 at 12:07 PM Vitaliy Makkoveev
> >  wrote:
> >>> On 25 May 2020, at 22:04, Sergey Ryazanov  wrote:
> >>> On Sat, May 23, 2020 at 3:07 PM Vitaliy Makkoveev
> >>>  wrote:
> >>>> For example, each pipex session should have unique pair of `protocol’ and
> >>>> `session_id’. These values are passed from userland. While the only
> >>>> instance of npppd(8) uses pipex(4) this is not the problem. But you
> >>>> introduce the case while pipex(4) will be used by multiple independent
> >>>> userland programs. At least, I have interest how you handle this.
> >>>
> >>> This should not be a problem here. npppd(8) support server mode only.
> >>> While my work is to implement acceleration for client side of L2TP
> >>> connection.
> >>
> >> I guess they can coexist. Also you can have multiple connections to
> >> ppp servers simultaneously.
> >
> > With 16 bits long session id field, according to birthday problem to
> > reach 0.9 collision probability I need 549 simultaneous sessions.
> > Should I still be worried or I have a time to complete integration
> > work and then update UDP  filter for love of the game?
>
> Why do you ask me? Do what you want.

I want to prioritize my todo list, and I in need of advice, is
possible collision is non-critical at the moment, or I missed
something and should solve it first?

-- 
Serge



Re: [PATCH] tcpdump: add ppp address/protocol compression support

2020-05-26 Thread Sergey Ryazanov
Hello!

On Mon, May 4, 2020 at 9:37 PM Sergey Ryazanov  wrote:
> Add support for parsing ppp frames with compressed address and(or)
> protocol fields. Since we have no apriory information than try to
> guess such frames by inability to parse a frame in a regular way.
>
> ok?

Does someone have any objections on this diff?

-- 
Sergey



Re: [RFC] pppd: add pipex(4) L2TP control support

2020-05-26 Thread Sergey Ryazanov
On Tue, May 26, 2020 at 11:31 AM Claudio Jeker  wrote:
> On Tue, May 26, 2020 at 09:22:28AM +0200, Martin Pieuchot wrote:
> > On 25/05/20(Mon) 21:42, Sergey Ryazanov wrote:
> > > Add dedicated option to activate kernel L2TP acceleration via
> > > the pipex(4). The options should be passed by a L2TP tunnel
> > > management daemon (e.g. xl2tpd).
> >
> > What is the difference between npppd(8) and pppd(8)?   Aren't those two
> > redundant?  Why did you choose to modify pppd(8) and not npppd(8)?
>
> npppd(8) is server only it can not establish a connection. pppd(8) on the
> other hand is more client side (but I think it can do both).

True.

> I think the split in userland makes sense (using npppd as LNS/LAC and pppd
> to connect to a ISP via PPP (even though we also use sppp/pppoe(4) for
> that). Now for the kernel side it would be great if the interface used
> would be the same for all ppp users. In this regard this is a step in the
> right direction.

Comparing addition of client support to npppd and reworking pppd to
support pppx(4), I will choose the npppd reworking. The pppd code is
the mess that is too tightly connected with TTY.

Moreover, pppd is designed to establish the PPP connection over any
type of serial line, including RS232 connected Dial-Up modem. So
introducing the pppx(4) support will require preserving of all
existing code *and* creation of a big module that is responsible
pppx(4) handling in case of L2TP connection. And such feature will
require a hard xl2tpd daemon reworking too. It is easier to rework
npppd or ever create a new L2TP client daemon from the scratch.

So I found a 3rd solution - add a pipex(4) support for the good
old-fashioned ppp(4) and a tiny option for pppd. And this my plan if
someone do not have a better solution.

> > > diff --git usr.sbin/pppd/ipcp.c usr.sbin/pppd/ipcp.c
> > > index 1296d897b14..e7a6dbd6ee7 100644
> > > --- usr.sbin/pppd/ipcp.c
> > > +++ usr.sbin/pppd/ipcp.c
> > > @@ -1251,6 +1251,10 @@ ipcp_up(f)
> > > return;
> > > }
> > >
> > > +   /* enable pipex(4), keep working if failed */
> > > +   if (pipex_conf.pr_protocol && !apipex(go->ouraddr, ho->hisaddr, mask))
> > > +   IPCPDEBUG((LOG_WARNING, "apipex failed"));
> > > +
> > >  #if (defined(SVR4) && (defined(SNI) || defined(__USLC__)))
> > > if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) {
> > > IPCPDEBUG((LOG_WARNING, "sifaddr failed"));
> > > @@ -1304,6 +1308,7 @@ ipcp_down(f)
> > >  if (demand) {
> > > sifnpmode(f->unit, PPP_IP, NPMODE_QUEUE);
> > >  } else {
> > > +   dpipex();
> > > sifdown(f->unit);
> > > ipcp_clear_addrs(f->unit);
> > >  }
> > > diff --git usr.sbin/pppd/options.c usr.sbin/pppd/options.c
> > > index 828f7cdce65..fe0e2e6b54b 100644
> > > --- usr.sbin/pppd/options.c
> > > +++ usr.sbin/pppd/options.c
> > > @@ -144,6 +144,9 @@ struct  bpf_program pass_filter;/* Filter program for 
> > > packets to pass */
> > >  struct bpf_program active_filter; /* Filter program for link-active 
> > > pkts */
> > >  pcap_t  pc;/* Fake struct pcap so we can compile 
> > > expr */
> > >  #endif
> > > +struct pipex_session_req pipex_conf = {/* pipex(4) session 
> > > configuration */
> > > +  .pr_protocol = 0,
> > > +};
> > >
> > >  /*
> > >   * Prototypes
> > > @@ -253,6 +256,8 @@ static int setactivefilter(char **);
> > >  static int setmslanman(char **);
> > >  #endif
> > >
> > > +static int setpipexl2tp(char **);
> > > +
> > >  static int number_option(char *, u_int32_t *, int);
> > >  static int int_option(char *, int *);
> > >  static int readable(int fd);
> > > @@ -391,6 +396,8 @@ static struct cmd {
> > >  {"ms-lanman", 0, setmslanman}, /* Use LanMan psswd when using 
> > > MS-CHAP */
> > >  #endif
> > >
> > > +{"pipex-l2tp", 6, setpipexl2tp},   /* set pipex(4) L2TP 
> > > parameters */
> > > +
> > >  {NULL, 0, NULL}
> > >  };
> > >
> > > @@ -2283,3 +2290,78 @@ setmslanman(argv)
> > >  return (1);
> > >  }
> > >  #endif
> > > +
> > > +static int
> > > +inet_atoss(cp, ss)
> > > +char *cp;
> > > +struct sockaddr_storage *ss;
> > > +{
> > > +struct sockaddr_in *sin = (struct sockad

Re: [PATCH] pipex(4): rework PPP input

2020-05-26 Thread Sergey Ryazanov
On Tue, May 26, 2020 at 12:07 PM Vitaliy Makkoveev
 wrote:
>> On 25 May 2020, at 22:04, Sergey Ryazanov  wrote:
>> On Sat, May 23, 2020 at 3:07 PM Vitaliy Makkoveev
>>  wrote:
>>> For example, each pipex session should have unique pair of `protocol’ and
>>> `session_id’. These values are passed from userland. While the only
>>> instance of npppd(8) uses pipex(4) this is not the problem. But you
>>> introduce the case while pipex(4) will be used by multiple independent
>>> userland programs. At least, I have interest how you handle this.
>>
>> This should not be a problem here. npppd(8) support server mode only.
>> While my work is to implement acceleration for client side of L2TP
>> connection.
>
> I guess they can coexist. Also you can have multiple connections to
> ppp servers simultaneously.

With 16 bits long session id field, according to birthday problem to
reach 0.9 collision probability I need 549 simultaneous sessions.
Should I still be worried or I have a time to complete integration
work and then update UDP  filter for love of the game?

-- 
Sergey



Re: [PATCH] pipex(4): rework PPP input

2020-05-25 Thread Sergey Ryazanov
Hello Vitaliy,

On Sat, May 23, 2020 at 3:07 PM Vitaliy Makkoveev
 wrote:
> > On 23 May 2020, at 13:11, Sergey Ryazanov  wrote:
> > On Wed, May 20, 2020 at 10:13 PM Vitaliy Makkoveev
> >  wrote:
> >> On Wed, May 20, 2020 at 04:08:01AM +0300, Sergey Ryazanov wrote:
> >>> On Tue, May 19, 2020 at 12:11 PM Vitaliy Makkoveev
> >>>  wrote:
> >>>> On Mon, May 04, 2020 at 10:03:40PM +0300, Sergey Ryazanov wrote:
> >>>>> Split checks from frame accepting with header removing in the common
> >>>>> PPP input function. This should fix packet capture on a PPP interfaces.
> >>>>
> >>>> Can you describe the problem you fix? As mpi@ pointed to me, reviewers
> >>>> are stupid and have no telepathy skills :)
> >>>
> >>> When I tried to capture packets on a ppp (4) interface (with pipex
> >>> activated), I noticed that all the PPP CCP frames were ok, but all the
> >>> ingress PPP IP frames were mangled, and they did not contain the PPP
> >>> header at all.
> >>
> >> This time only pppx(4) and pppac(4) have pipex(4) support.
> >
> > Yes, and as I wrote in the first mail, now I am working on ppp(4) &
> > pipex(4) integration to speed up client side of L2TP.
>
> May be you can share you work? Not for commit, but for feedback.
>

I send a couple of diffs in separate mails. First change is for ppp(4)
 to support pipex(4) acceleration in DL path. Second diff adds a new
option for pppd to control pipex activation.

We will need also to update xl2tpd package to teach it how to
configure pppd for pipex usage. This is quite simple change, but it
still require some cleanup so I do not publish it yet.

> For example, each pipex session should have unique pair of `protocol’ and
> `session_id’. These values are passed from userland. While the only
> instance of npppd(8) uses pipex(4) this is not the problem. But you
> introduce the case while pipex(4) will be used by multiple independent
> userland programs. At least, I have interest how you handle this.

This should not be a problem here. npppd(8) support server mode only.
While my work is to implement acceleration for client side of L2TP
connection.

Anyway if a session collision become a case, we could additionally
demux ingress traffic by the destination UDP port.

-- 
Sergey



[RFC] ppp: add pipex(4) support

2020-05-25 Thread Sergey Ryazanov
Add minimal support for integration with pipex(4). Initialize interface
structure, pass IOCTLs to pipex(4) specific handler, etc.

Acceleration is working only in the DL path only at the moment.

Modification is not ready for applying. Work still in process.
---
 sys/net/if_ppp.c| 16 
 sys/net/if_pppvar.h |  4 
 sys/net/ppp_tty.c   | 17 +
 3 files changed, 37 insertions(+)

diff --git sys/net/if_ppp.c sys/net/if_ppp.c
index 3f03d18b6ab..482eef37732 100644
--- sys/net/if_ppp.c
+++ sys/net/if_ppp.c
@@ -129,6 +129,10 @@
 #include 
 #include 
 
+#ifdef PIPEX
+#include 
+#endif
+
 #include "bpfilter.h"
 
 #ifdef VJC
@@ -198,6 +202,9 @@ pppattach(void)
 {
LIST_INIT(_softc_list);
if_clone_attach(_cloner);
+#ifdef PIPEX
+   pipex_init();
+#endif
 }
 
 int
@@ -228,6 +235,11 @@ ppp_clone_create(struct if_clone *ifc, int unit)
 #if NBPFILTER > 0
bpfattach(>if_bpf, ifp, DLT_PPP, PPP_HDRLEN);
 #endif
+
+#ifdef PIPEX
+   pipex_iface_init(>sc_pipex_iface, >sc_if);
+#endif
+
NET_LOCK();
LIST_INSERT_HEAD(_softc_list, sc, sc_list);
NET_UNLOCK();
@@ -247,6 +259,10 @@ ppp_clone_destroy(struct ifnet *ifp)
LIST_REMOVE(sc, sc_list);
NET_UNLOCK();
 
+#ifdef PIPEX
+   pipex_iface_fini(>sc_pipex_iface);
+#endif
+
if_detach(ifp);
 
free(sc, M_DEVBUF, 0);
diff --git sys/net/if_pppvar.h sys/net/if_pppvar.h
index 1c4dd9977b5..57f3b76c4f6 100644
--- sys/net/if_pppvar.h
+++ sys/net/if_pppvar.h
@@ -139,6 +139,10 @@ struct ppp_softc {
u_char  sc_rawin[16];   /* chars as received */
int sc_rawin_count; /* # in sc_rawin */
LIST_ENTRY(ppp_softc) sc_list;  /* all ppp interfaces */
+
+#ifdef PIPEX
+   struct pipex_iface_context sc_pipex_iface;  /* pipex context */
+#endif
 };
 
 #ifdef _KERNEL
diff --git sys/net/ppp_tty.c sys/net/ppp_tty.c
index 124b9df59ac..93bcd62ae4b 100644
--- sys/net/ppp_tty.c
+++ sys/net/ppp_tty.c
@@ -122,6 +122,10 @@
 #include 
 #endif
 
+#ifdef PIPEX
+#include 
+#endif
+
 #include 
 #include 
 #include 
@@ -425,6 +429,19 @@ ppptioctl(struct tty *tp, u_long cmd, caddr_t data, int 
flag, struct proc *p)
bcopy(sc->sc_asyncmap, data, sizeof(sc->sc_asyncmap));
break;
 
+#ifdef PIPEX
+case PIPEXSMODE:
+case PIPEXGMODE:
+case PIPEXASESSION:
+case PIPEXDSESSION:
+case PIPEXCSESSION:
+case PIPEXGSTAT:
+   if ((error = suser(p)) != 0)
+   break;
+   error = pipex_ioctl(>sc_pipex_iface, cmd, data);
+   break;
+#endif
+
 default:
NET_LOCK();
error = pppioctl(sc, cmd, data, flag, p);
-- 
2.26.0



[RFC] pppd: add pipex(4) L2TP control support

2020-05-25 Thread Sergey Ryazanov
Add dedicated option to activate kernel L2TP acceleration via
the pipex(4). The options should be passed by a L2TP tunnel
management daemon (e.g. xl2tpd).

This diff is complete, but kernel support in ppp(4) is not ready.
---
 usr.sbin/pppd/ipcp.c|  5 +++
 usr.sbin/pppd/options.c | 82 +
 usr.sbin/pppd/pppd.8| 18 +
 usr.sbin/pppd/pppd.h|  7 
 usr.sbin/pppd/sys-bsd.c | 56 
 5 files changed, 168 insertions(+)

diff --git usr.sbin/pppd/ipcp.c usr.sbin/pppd/ipcp.c
index 1296d897b14..e7a6dbd6ee7 100644
--- usr.sbin/pppd/ipcp.c
+++ usr.sbin/pppd/ipcp.c
@@ -1251,6 +1251,10 @@ ipcp_up(f)
return;
}
 
+   /* enable pipex(4), keep working if failed */
+   if (pipex_conf.pr_protocol && !apipex(go->ouraddr, ho->hisaddr, mask))
+   IPCPDEBUG((LOG_WARNING, "apipex failed"));
+
 #if (defined(SVR4) && (defined(SNI) || defined(__USLC__)))
if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) {
IPCPDEBUG((LOG_WARNING, "sifaddr failed"));
@@ -1304,6 +1308,7 @@ ipcp_down(f)
 if (demand) {
sifnpmode(f->unit, PPP_IP, NPMODE_QUEUE);
 } else {
+   dpipex();
sifdown(f->unit);
ipcp_clear_addrs(f->unit);
 }
diff --git usr.sbin/pppd/options.c usr.sbin/pppd/options.c
index 828f7cdce65..fe0e2e6b54b 100644
--- usr.sbin/pppd/options.c
+++ usr.sbin/pppd/options.c
@@ -144,6 +144,9 @@ struct  bpf_program pass_filter;/* Filter program for 
packets to pass */
 struct bpf_program active_filter; /* Filter program for link-active pkts */
 pcap_t  pc;/* Fake struct pcap so we can compile expr */
 #endif
+struct pipex_session_req pipex_conf = {/* pipex(4) session 
configuration */
+  .pr_protocol = 0,
+};
 
 /*
  * Prototypes
@@ -253,6 +256,8 @@ static int setactivefilter(char **);
 static int setmslanman(char **);
 #endif
 
+static int setpipexl2tp(char **);
+
 static int number_option(char *, u_int32_t *, int);
 static int int_option(char *, int *);
 static int readable(int fd);
@@ -391,6 +396,8 @@ static struct cmd {
 {"ms-lanman", 0, setmslanman}, /* Use LanMan psswd when using MS-CHAP 
*/
 #endif
 
+{"pipex-l2tp", 6, setpipexl2tp},   /* set pipex(4) L2TP parameters */
+
 {NULL, 0, NULL}
 };
 
@@ -2283,3 +2290,78 @@ setmslanman(argv)
 return (1);
 }
 #endif
+
+static int
+inet_atoss(cp, ss)
+char *cp;
+struct sockaddr_storage *ss;
+{
+struct sockaddr_in *sin = (struct sockaddr_in *)ss;
+char *c, *p;
+unsigned port;
+
+if ((c = strchr(cp, ':')) == NULL)
+   return 0;
+*c = '\0';
+if (!inet_aton(cp, >sin_addr))
+   return 0;
+if (!(port = strtoul(c + 1, , 10)) || *p != '\0')
+   return 0;
+sin->sin_port = htons(port);
+sin->sin_family = AF_INET;
+ss->ss_len = sizeof(*sin);
+
+return 1;
+}
+
+static int
+strtou16(str, valp)
+char *str;
+uint16_t *valp;
+{
+char *ptr;
+
+*valp = strtoul(str, , 0);
+
+return *ptr == '\0' ? 1 : 0;
+}
+
+static int
+setpipexl2tp(argv)
+char **argv;
+{
+BZERO((char *)_conf, sizeof(pipex_conf));
+
+if (!inet_atoss(argv[0], _conf.pr_local_address)) {
+   option_error("pipex-l2tp: invalid local address of tunnel: %s", 
argv[0]);
+   return 0;
+}
+if (!inet_atoss(argv[1], _conf.pr_peer_address)) {
+   option_error("pipex-l2tp: invalid peer address of tunnel: %s", argv[1]);
+   return 0;
+}
+if (!strtou16(argv[2], _conf.pr_proto.l2tp.tunnel_id)) {
+   option_error("pipex-l2tp: invalid local tunnel id: %s", argv[2]);
+   return 0;
+}
+if (!strtou16(argv[3], _conf.pr_proto.l2tp.peer_tunnel_id)) {
+   option_error("pipex-l2tp: invalid peer tunnel id: %s", argv[3]);
+   return 0;
+}
+if (!strtou16(argv[4], _conf.pr_session_id)) {
+   option_error("pipex-l2tp: invalid local call id: %s", argv[4]);
+   return 0;
+}
+if (!strtou16(argv[5], _conf.pr_peer_session_id)) {
+   option_error("pipex-l2tp: invalid peer call id: %s", argv[5]);
+   return 0;
+}
+
+/* Indicate address field presense */
+pipex_conf.pr_ppp_flags = PIPEX_PPP_HAS_ACF;
+
+/* Finally set the protocol type to implicitly indicate config validity */
+pipex_conf.pr_protocol = PIPEX_PROTO_L2TP;
+
+return 1;
+}
diff --git usr.sbin/pppd/pppd.8 usr.sbin/pppd/pppd.8
index 5fba6f1714d..6a7f6e01c09 100644
--- usr.sbin/pppd/pppd.8
+++ usr.sbin/pppd/pppd.8
@@ -829,6 +829,24 @@ option is used.
 .It Cm xonxoff
 Use software flow control (i.e., XON/XOFF) to control the flow of data on
 the serial port.
+.It Cm pipex-l2tp Ar ltunaddr ptunaddr ltunid ptunid lcallid pcallid
+OpenBSD specific. Activate and configure kernel L2TP acceleration. Set
+pipex(4) local tunnel address to
+.Ar ltunaddr ,
+peer tunnel address to
+.Ar ptunaddr ,
+local L2TP tunnel id to
+.Ar ltunid ,
+peer L2TP tunnel id to
+.Ar ptunid ,
+local L2TP call id (local session 

Re: [PATCH] pipex(4): rework PPP input

2020-05-23 Thread Sergey Ryazanov
Hello,

On Wed, May 20, 2020 at 10:13 PM Vitaliy Makkoveev
 wrote:
> On Wed, May 20, 2020 at 04:08:01AM +0300, Sergey Ryazanov wrote:
> > On Tue, May 19, 2020 at 12:11 PM Vitaliy Makkoveev
> >  wrote:
> > > On Mon, May 04, 2020 at 10:03:40PM +0300, Sergey Ryazanov wrote:
> > > > Split checks from frame accepting with header removing in the common
> > > > PPP input function. This should fix packet capture on a PPP interfaces.
> > >
> > > Can you describe the problem you fix? As mpi@ pointed to me, reviewers
> > > are stupid and have no telepathy skills :)
> >
> > When I tried to capture packets on a ppp (4) interface (with pipex
> > activated), I noticed that all the PPP CCP frames were ok, but all the
> > ingress PPP IP frames were mangled, and they did not contain the PPP
> > header at all.
>
> This time only pppx(4) and pppac(4) have pipex(4) support.

Yes, and as I wrote in the first mail, now I am working on ppp(4) &
pipex(4) integration to speed up client side of L2TP.

> I don't see
> packet capture problems on them. Can you catch and share how to
> reproduce this problem with pppx(4) or pppac(4)?
>
> Also did you test your diff with pppx(4) and pppac(4)?

I am entirely missed the fact that pppx(4) also have IFT_PPP type.
Thank you for pointing me.

I will recheck pppx(4) work and return as soon as I will have a better solution.

 --
Sergey



Re: [PATCH] pipex(4): rework PPP input

2020-05-19 Thread Sergey Ryazanov
2 Hi Vitaliy,

On Tue, May 19, 2020 at 12:11 PM Vitaliy Makkoveev
 wrote:
> On Mon, May 04, 2020 at 10:03:40PM +0300, Sergey Ryazanov wrote:
> > Split checks from frame accepting with header removing in the common
> > PPP input function. This should fix packet capture on a PPP interfaces.
>
> Can you describe the problem you fix? As mpi@ pointed to me, reviewers
> are stupid and have no telepathy skills :)

When I tried to capture packets on a ppp (4) interface (with pipex
activated), I noticed that all the PPP CCP frames were ok, but all the
ingress PPP IP frames were mangled, and they did not contain the PPP
header at all.

Then I started digging the code and came across the fact that pipex
has two packet capture points. One place is in pipex_ip_input(), where
pure IP packets (without a PPP header) are passed to bpf, and the
other is in pipex_ppp_input(), where only CCP frames are passed to bpf
and only if the associated network interface is of PPP type.

My first thought was to add another one hook to the pipex_ppp_input()
to intercept IP frames before the PPP header stripping. But then I
spotted that pipex_ppp_input() have a common pattern in the frames
processing, but it was poorly expressed since before the proposed
change the code is looks like this (in pseudo code):

if COMP
COMP sanity checks
ppp header stripping<- duplicate #1
call MPPE handler
exit
if CCP
CCP sanity checks
bpf call
ppp header stripping<- duplicate #2
call MPPE handler
exit
ppp header stripping<- duplicate #3
packet data alignment
if IP
IP sanity checks
call IP handler
exit
if IPv6
IPv6 sanity checks
call IPv6 handler
exit
if unknown PPP frame type
produce a big fat error message

As you can see for each frame type the code performs a specific sanity
check, strips the PPP header and then call a frame specific handler.
Also CCP frames on a ppp(4) interface are passed to bpf.

So I rearrange the code to make I a bit more clear:
* group sanity checks in the beginning of the function;
* place bpf call for ppp(4) interfaces after sanity checks, but
_before_ PPP header stripping;
* place the header stripping common for all types with optional data alignment;
* group frame specific handler calls in the end of the function;
* use switch/case to help a compiler and human readers :)

Now the function code is looks like this:

if COMP
COMP sanity checks
if CCP
CCP sanity checks
if IP
IP sanity checks and prepare for alignment
if IPv6
IPv6 sanity checks and prepare for alignment
if unknown PPP frame type
produce a big fat error message
call bpf for ppp(4) interfaces while frame still has the PPP header
strip the ppp header and perform optional alignment
if COMP
COMP sanity checks
if CCP
CCP sanity checks
if IP
IP sanity checks and prepare for alignment
if IPv6
IPv6 sanity checks and prepare for alignment

Diff is just unable to express such change in a human friendly way :(
It is better to look at the code before diff applying and after to see
the change.

The final hank just blocks stripped IP packets passing to bpf on
ppp(4) network interfaces to avoid duplicate (and mangled) packets in
a dump.

So, after the change we will get: function behaves as early, tcpdump
perfectly sniffs on a ppp interface with activated pipex, checks are
performed before expensive packet modifications, and function code is
readable and now it is clear what exactly function do for each type of
frames.

Oh, also pipex.c become shorter by the 13 lines.

> Also your diff does two different things: (1) split frames checks and
> input, and (2) modify frames passing to bpf(4). I guess you should split
> your diff by two different.

The bpf call modifications just prevent frame duplication in the dump.
So I think Its better to keep them here.

Buf if someone is against such wide modifications, then I am Ok to
send two patches: one for mangled packets dumping prevention and one
for PPP input rework.

> I did some inlined comments below.
>
> >
> > Also forbid IP/IPv6 frames (without PPP header) passing to BPF on
> > PPP interfaces to avoid mess.
> >
> > Initialy this change was made as a part of pipex(4) and ppp(4)
> > integration work. But, since this change make the core a bit more clear
> > I would like to publish it now.
> >
> > Ok?
> >
> > ---
> >  sys/net/pipex.c | 95 -
> >  1 file changed, 54 insertions(+), 41 deletions(-)
> >
> > diff --git sys/net/pipex.c sys/net/pipex.c
> > index c433e4beaa6..e0066a61598 100644
> > --- sys/net/pipex.c
> > +++ sys/net/pipex.c
> > @@ -970,41 +970,68 @@ drop:
> >  Static void
> >  pipex_ppp_input(struct mbuf *m0, struct pipex_session *session, int 
> > decrypted)
> >  {
> &

[PATCH] pipex(4): rework PPP input

2020-05-04 Thread Sergey Ryazanov
Split checks from frame accepting with header removing in the common
PPP input function. This should fix packet capture on a PPP interfaces.

Also forbid IP/IPv6 frames (without PPP header) passing to BPF on
PPP interfaces to avoid mess.

Initialy this change was made as a part of pipex(4) and ppp(4)
integration work. But, since this change make the core a bit more clear
I would like to publish it now.

Ok?

---
 sys/net/pipex.c | 95 -
 1 file changed, 54 insertions(+), 41 deletions(-)

diff --git sys/net/pipex.c sys/net/pipex.c
index c433e4beaa6..e0066a61598 100644
--- sys/net/pipex.c
+++ sys/net/pipex.c
@@ -970,41 +970,68 @@ drop:
 Static void
 pipex_ppp_input(struct mbuf *m0, struct pipex_session *session, int decrypted)
 {
-   int proto, hlen = 0;
+   int proto, hlen = 0, align = 0;
struct mbuf *n;
 
KASSERT(m0->m_pkthdr.len >= PIPEX_PPPMINLEN);
proto = pipex_ppp_proto(m0, session, 0, );
+   switch (proto) {
+   case PPP_IP:
+   if (session->ip_forward == 0)
+   goto drop;
+   if (!decrypted && pipex_session_is_mppe_required(session))
+   /*
+* if ip packet received when mppe
+* is required, discard it.
+*/
+   goto drop;
+   align = 1;
+   break;
+#ifdef INET6
+   case PPP_IPV6:
+   if (session->ip6_forward == 0)
+   goto drop;
+   if (!decrypted && pipex_session_is_mppe_required(session))
+   /*
+* if ip packet received when mppe
+* is required, discard it.
+*/
+   goto drop;
+   align = 1;
+   break;
+#endif
 #ifdef PIPEX_MPPE
-   if (proto == PPP_COMP) {
+   case PPP_COMP:
if (decrypted)
goto drop;
 
/* checked this on ppp_common_input() already. */
KASSERT(pipex_session_is_mppe_accepted(session));
-
-   m_adj(m0, hlen);
-   pipex_mppe_input(m0, session);
-   return;
-   }
-   if (proto == PPP_CCP) {
+   break;
+   case PPP_CCP:
if (decrypted)
goto drop;
+   break;
+#endif
+   default:
+   if (decrypted)
+   goto drop;
+   /* protocol must be checked on pipex_common_input() already */
+   KASSERT(0);
+   goto drop;
+   }
 
 #if NBPFILTER > 0
-   {
+   {
struct ifnet *ifp = session->pipex_iface->ifnet_this;
+
if (ifp->if_bpf && ifp->if_type == IFT_PPP)
bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_IN);
-   }
-#endif
-   m_adj(m0, hlen);
-   pipex_ccp_input(m0, session);
-   return;
}
 #endif
+
m_adj(m0, hlen);
-   if (!ALIGNED_POINTER(mtod(m0, caddr_t), uint32_t)) {
+   if (align && !ALIGNED_POINTER(mtod(m0, caddr_t), uint32_t)) {
n = m_dup_pkt(m0, 0, M_NOWAIT);
if (n == NULL)
goto drop;
@@ -1014,35 +1041,21 @@ pipex_ppp_input(struct mbuf *m0, struct pipex_session 
*session, int decrypted)
 
switch (proto) {
case PPP_IP:
-   if (session->ip_forward == 0)
-   goto drop;
-   if (!decrypted && pipex_session_is_mppe_required(session))
-   /*
-* if ip packet received when mppe
-* is required, discard it.
-*/
-   goto drop;
pipex_ip_input(m0, session);
-   return;
+   break;
 #ifdef INET6
case PPP_IPV6:
-   if (session->ip6_forward == 0)
-   goto drop;
-   if (!decrypted && pipex_session_is_mppe_required(session))
-   /*
-* if ip packet received when mppe
-* is required, discard it.
-*/
-   goto drop;
pipex_ip6_input(m0, session);
-   return;
+   break;
+#endif
+#ifdef PIPEX_MPPE
+   case PPP_COMP:
+   pipex_mppe_input(m0, session);
+   break;
+   case PPP_CCP:
+   pipex_ccp_input(m0, session);
+   break;
 #endif
-   default:
-   if (decrypted)
-   goto drop;
-   /* protocol must be checked on pipex_common_input() already */
-   KASSERT(0);
-   goto drop;
}
 
return;
@@ -1105,7 +1118,7 @@ pipex_ip_input(struct mbuf *m0, struct pipex_session 
*session)
len = 

[PATCH] ppp(4): use common bpf filter hook

2020-05-04 Thread Sergey Ryazanov
Use bpf filter hook from the common interface structure. This simplifies
the code by unifying it and prepare ppp(4) for pipex(4) support.

Ok?

---
 sys/net/if_ppp.c| 16 
 sys/net/if_pppvar.h |  1 -
 2 files changed, 8 insertions(+), 9 deletions(-)

diff --git sys/net/if_ppp.c sys/net/if_ppp.c
index 192ec7c91e0..4cba9a8778c 100644
--- sys/net/if_ppp.c
+++ sys/net/if_ppp.c
@@ -204,9 +204,11 @@ int
 ppp_clone_create(struct if_clone *ifc, int unit)
 {
struct ppp_softc *sc;
+   struct ifnet *ifp;
 
sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO);
sc->sc_unit = unit;
+   ifp = >sc_if;
snprintf(sc->sc_if.if_xname, sizeof sc->sc_if.if_xname, "%s%d",
ifc->ifc_name, unit);
sc->sc_if.if_softc = sc;
@@ -224,7 +226,7 @@ ppp_clone_create(struct if_clone *ifc, int unit)
if_attach(>sc_if);
if_alloc_sadl(>sc_if);
 #if NBPFILTER > 0
-   bpfattach(>sc_bpf, >sc_if, DLT_PPP, PPP_HDRLEN);
+   bpfattach(>if_bpf, ifp, DLT_PPP, PPP_HDRLEN);
 #endif
NET_LOCK();
LIST_INSERT_HEAD(_softc_list, sc, sc_list);
@@ -754,11 +756,9 @@ pppoutput(struct ifnet *ifp, struct mbuf *m0, struct 
sockaddr *dst,
}
 
 #if NBPFILTER > 0
-   /*
-* See if bpf wants to look at the packet.
-*/
-   if (sc->sc_bpf)
-   bpf_mtap(sc->sc_bpf, m0, BPF_DIRECTION_OUT);
+   /* See if bpf wants to look at the packet. */
+   if (ifp->if_bpf)
+   bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
 #endif
 
/*
@@ -1369,8 +1369,8 @@ ppp_inproc(struct ppp_softc *sc, struct mbuf *m)
 
 #if NBPFILTER > 0
/* See if bpf wants to look at the packet. */
-   if (sc->sc_bpf)
-   bpf_mtap(sc->sc_bpf, m, BPF_DIRECTION_IN);
+   if (ifp->if_bpf)
+   bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
 #endif
 
rv = 0;
diff --git sys/net/if_pppvar.h sys/net/if_pppvar.h
index 87f7d1798bb..9dc774a0515 100644
--- sys/net/if_pppvar.h
+++ sys/net/if_pppvar.h
@@ -113,7 +113,6 @@ struct ppp_softc {
struct  mbuf *sc_togo;  /* output packet ready to go */
struct  mbuf_list sc_npqueue;   /* output packets not to be sent yet */
struct  pppstat sc_stats;   /* count of bytes/pkts sent/rcvd */
-   caddr_t sc_bpf; /* hook for BPF */
enumNPmode sc_npmode[NUM_NP]; /* what to do with each NP */
struct  compressor *sc_xcomp;   /* transmit compressor */
void*sc_xc_state;   /* transmit compressor state */
-- 
2.26.0



[PATCH] tcpdump: add ppp address/protocol compression support

2020-05-04 Thread Sergey Ryazanov
Add support for parsing ppp frames with compressed address and(or)
protocol fields. Since we have no apriory information than try to
guess such frames by inability to parse a frame in a regular way.

ok?

---
 usr.sbin/tcpdump/print-ppp.c | 29 +
 1 file changed, 17 insertions(+), 12 deletions(-)

diff --git usr.sbin/tcpdump/print-ppp.c usr.sbin/tcpdump/print-ppp.c
index 21f5d154847..60027178942 100644
--- usr.sbin/tcpdump/print-ppp.c
+++ usr.sbin/tcpdump/print-ppp.c
@@ -341,20 +341,26 @@ void
 ppp_print(const u_char *p, u_int length)
 {
uint16_t proto;
-   int l;
+   int l, pfl;
 
l = snapend - p;
 
-   if (l < sizeof(proto)) {
+   /* Check for compressed protocol field */
+   if (l >= 1 && (p[0] & 0x1) != 0)
+   pfl = sizeof(uint8_t);
+   else
+   pfl = sizeof(uint16_t);
+
+   if (l < pfl) {
printf("[|ppp]");
return;
}
 
-   proto = EXTRACT_16BITS(p);
+   proto = pfl == sizeof(uint8_t) ? p[0] : EXTRACT_16BITS(p);
 
-   p += sizeof(proto);
-   l -= sizeof(proto);
-   length -= sizeof(proto);
+   p += pfl;
+   l -= pfl;
+   length -= pfl;
 
if (eflag)
ppp_protoname(proto);
@@ -1385,12 +1391,11 @@ ppp_hdlc_print(const u_char *p, u_int length)
address = p[0];
control = p[1];
 
-   p += sizeof(address) + sizeof(control);
-   l -= sizeof(address) + sizeof(control);
-   length -= sizeof(address) + sizeof(control);
-
switch (address) {
case 0xff: /* All-Stations */
+   p += sizeof(address) + sizeof(control);
+   l -= sizeof(address) + sizeof(control);
+   length -= sizeof(address) + sizeof(control);
if (eflag)
printf("%02x %02x %u ", address, control, length);
 
@@ -1402,8 +1407,8 @@ ppp_hdlc_print(const u_char *p, u_int length)
ppp_print(p, length);
break;
 
-   default:
-   printf("ppp address 0x%02x unknown", address);
+   default: /* Assume address compression */
+   ppp_print(p, length);
break;
}
return;
-- 
2.26.0



L2TP: rise download speed with ppp(4) + pipex(4)

2016-06-21 Thread Sergey Ryazanov
Hello,

I would like to announce that I finally reached 80 mbps of download
via pure L2TP tunnel (without IPsec).

I digged through ppp(4) and pppd(8) code several times and I could not
find any bottlenecks. Looks like we need to change whole design of
ppp(4) to reach any usable download speed.

So I change direction and add pipex(4) support to ppp(4), only in Rx
path for now. And the same machine (Pentium D @3GHz) give me 80 mbps
of download rate instead of 20 mbps when run without pipex.

If somebody wants to reproduce the trick, you need a couple of patches
(one for ppp driver and second for xl2tpd) and utility to configure
pipex session (my version is here
https://github.com/rsa9000/pipexctl). Patches inlined below and
attached to mail due to gmail's rule to mangle whitespaces.

First of all you need to patch and rebuild the kernel. Then you need
to patch xl2tpd package and rebuild it too. Then activate pipex via
sysctl, configure and start xl2tpd as usual. Make sure that packets
are successfully traveling via established link.

Then the most trickly part: you need parse ouput of xl2tpd (to console
or syslog) and fetch Tunnel-Id & Session-Id values of running tunnel.
Then run (consult pipex man page for parameters description):
# pipexctl addsess l2tp 

Command should looks like:
# pipexctl addsess l2tp  AA  BB  A.B.C.D  E.F.G.H 255.255.255.0
I.J.K.L:1701  M.N.O.P:1701  CC  DD

Actually most parameters except your Session-Id could be zero.

My further plans includes following actions:
 - add pipex support to Tx path of ppp(4)
 - backport plugins support from upstream to pppd(8)
 - make a plugin for pppd(8) to facilitate pipex usage (a-la pppol2tp for Linux)
 - add pipex plugin configuration support to xl2tpd (both to our port
and to upstream)

I would like to ask, does someone have any objections against such changes?

I would like to complete this work until next release, but it all
depends on whether I have free time or not.

Kernel patch:
diff -ru sys.orig/net/if_ppp.c sys/net/if_ppp.c
--- sys.orig/net/if_ppp.c 2015-11-20 09:22:09.0 +0300
+++ sys/net/if_ppp.c 2016-06-21 02:41:59.0 +0300
@@ -129,6 +129,10 @@
 #include 
 #include 

+#ifdef PIPEX
+#include 
+#endif
+
 #include "bpfilter.h"

 #ifdef VJC
@@ -199,6 +203,9 @@
 {
  LIST_INIT(_softc_list);
  if_clone_attach(_cloner);
+#ifdef PIPEX
+ pipex_init();
+#endif
 }

 int
@@ -236,6 +243,10 @@
  LIST_INSERT_HEAD(_softc_list, sc, sc_list);
  splx(s);

+#ifdef PIPEX
+ pipex_iface_init(>pipex_iface, >sc_if);
+#endif
+
  return (0);
 }

@@ -248,6 +259,10 @@
  if (sc->sc_devp != NULL)
  return (EBUSY);

+#ifdef PIPEX
+ pipex_iface_fini(>pipex_iface);
+#endif
+
  s = splnet();
  LIST_REMOVE(sc, sc_list);
  splx(s);
@@ -564,6 +579,19 @@
  break;
 #endif

+#ifdef PIPEX
+ case PIPEXSMODE:
+ case PIPEXGMODE:
+ case PIPEXASESSION:
+ case PIPEXDSESSION:
+ case PIPEXCSESSION:
+ case PIPEXGSTAT:
+ s = splnet();
+ error = pipex_ioctl(>pipex_iface, cmd, data);
+ splx(s);
+ return error;
+#endif
+
  default:
  return (-1);
  }
diff -ru sys.orig/net/if_pppvar.h sys/net/if_pppvar.h
--- sys.orig/net/if_pppvar.h 2015-11-06 12:04:36.0 +0300
+++ sys/net/if_pppvar.h 2016-06-21 02:41:59.0 +0300
@@ -140,6 +140,10 @@
  u_char sc_rawin[16]; /* chars as received */
  int sc_rawin_count; /* # in sc_rawin */
  LIST_ENTRY(ppp_softc) sc_list; /* all ppp interfaces */
+
+#ifdef PIPEX
+ struct pipex_iface_context pipex_iface; /* pipex context */
+#endif
 };

 #ifdef _KERNEL
diff -ru sys.orig/net/ppp_tty.c sys/net/ppp_tty.c
--- sys.orig/net/ppp_tty.c 2016-01-25 21:47:00.0 +0300
+++ sys/net/ppp_tty.c 2016-06-21 02:41:59.0 +0300
@@ -122,6 +122,10 @@
 #include 
 #endif

+#ifdef PIPEX
+#include 
+#endif
+
 #include 
 #include 
 #include 

x2tpd patch:
--- network.c.orig
+++ network.c
@@ -25,6 +25,10 @@
 #ifndef LINUX
 # include 
 #endif
+#ifdef OPENBSD
+#include 
+#include 
+#endif
 #include "l2tp.h"
 #include "ipsecmast.h"
 #include "misc.h"/* for IPADDY macro */
@@ -83,6 +87,10 @@

 #endif

+arg=1;
+if (setsockopt(server_socket, IPPROTO_IP, IP_PIPEX, ,
sizeof(arg)) != 0)
+l2tp_log(LOG_CRIT, "setsockopt pipex: %s\n", strerror(errno));
+
 #ifdef USE_KERNEL
 if (gconfig.forceuserspace)
 {

-- 
Sergey
diff -ru sys.orig/net/if_ppp.c sys/net/if_ppp.c
--- sys.orig/net/if_ppp.c	2015-11-20 09:22:09.0 +0300
+++ sys/net/if_ppp.c	2016-06-21 02:41:59.0 +0300
@@ -129,6 +129,10 @@
 #include 
 #include 
 
+#ifdef PIPEX
+#include 
+#endif
+
 #include "bpfilter.h"
 
 #ifdef VJC
@@ -199,6 +203,9 @@
 {
 	LIST_INIT(_softc_list);
 	if_clone_attach(_cloner);
+#ifdef PIPEX
+	pipex_init();
+#endif
 }
 
 int
@@ -236,6 +243,10 @@
 	LIST_INSERT_HEAD(_softc_list, sc, sc_list);
 	splx(s);
 
+#ifdef PIPEX
+	pipex_iface_init(>pipex_iface, >sc_if);
+#endif
+
 	return (0);
 }
 
@@ -248,6 +259,10 @@
 	if (sc->sc_devp != NULL)
 		return (EBUSY);
 
+#ifdef PIPEX
+	pipex_iface_fini(>pipex_iface);
+#endif
+
 	s = splnet();
 	

Re: Pure L2TP client upload performance

2015-07-07 Thread Sergey Ryazanov
 2015-06-26 9:20 GMT+03:00 Claudio Jeker cje...@diehard.n-r-g.com:
 On Fri, Jun 26, 2015 at 04:59:32AM +0300, Sergey Ryazanov wrote:
 Hello,

 during building l2tp tunnel with xl2tpd-1.3.1 I was faced with its too
 low  upload  performance.  When  download,  the  speed is 20 mbit/s at
 nearly  100% CPU utilization. CPU is Pentium D 930 3 GHz. When upload,
 the speed is below 2 mbit/s at nearly zero CPU utilization.

 First,  I  examined xl2tpd code and did not find any potential issues.
 Then  I  compiled  it with -pg option and do a quick test with help of
 iperf(1):  4  TCP  flows,  direction  is toward the L2TP server, 2 min
 test.   Then  I run gprof and got pretty strange output:

 [skip]

 During  upload  tests, everything looks like if xl2tpd doesn't perform
 any work and stucks somewhere in I/O operation.

 May  be  there are some options, what could be tuned to speedup ppp(4)
 I/O  performance  or  did  I missed something during my tests? I am in
 doubts. Any clues?


 Can you get a ktrace output to figure out what write is doing?
 Could it be that it busy loops with EINTR or EAGAIN?
 It sure smells like something is going on there.


 I did make the trace, which shows that write(2) works good, there are no
 errors:
 # kdump -f ktrace.out-0-tx | grep 'RET   write' | wc -l
23999
 # kdump -f ktrace.out-0-tx | grep 'RET   write.*errno' | wc -l
0

 That was bad news. Let's talk about something good. I finally found a way
 to speed up the upload. I got 91 mbit/s, as reported by speedtest.net,
 over 100 mbit Ethernet link (at 100% CPU utilization, with the patched
 non-SMP kernel).

 Looks like the issue is caused by too small size of pty output buffer, and
 too small watermarks, which control the pty buffer filling. When pty driver
 requests the tty allocation, it passes 0 as baud rate. For any rates, which
 is less or equal to 115200, tty driver allocates an output buffer of size
 of 1024 byte. And most likely, hardcoded watermarks in the ppp discipline
 code are selected according to this buffer size. May be these values were
 reasonable for 56k modems, but not for 100 mbit uplink.

 Patch for tests is inlined below. All numbers are arbitrary selected values.
 I just took first reasonable values and got a positive result, without any
 further experiments.

 This patch is not suitable for merging, since it just quick and dirty fix.
 To solve the issue in more generic way I see several approaches, each of
 which has pros and cons:
 (a) increase default value (as in this patch);
 (b) provide some API (IOCTL) to control buffer size from pppd(8);
 (c) make some hack that would reveal pty for high-speed links and increase
 their buffer.

 Any thoughts?

 P.S. If I can get 91 mbit/s of upload rate, then why I get only 20 mbit/s
 of download rate on the same machine?

 Index: kern/tty_pty.c
 ===
 RCS file: /cvs/src/sys/kern/tty_pty.c,v
 retrieving revision 1.70
 diff -u -p -r1.70 tty_pty.c
 --- kern/tty_pty.c  10 Feb 2015 21:56:10 -  1.70
 +++ kern/tty_pty.c  28 Jun 2015 14:18:16 -
 @@ -58,6 +58,7 @@
  #include sys/rwlock.h
  
  #define BUFSIZ 100 /* Chunk size iomoved to/from user */
 +#define PTY_DEF_BAUD 100
  
  /*
   * pts == /dev/tty[p-zP-T][0-9a-zA-Z]
 @@ -192,7 +193,7 @@ check_pty(int minor)
 if (!pt_softc[minor]) {
 pti = malloc(sizeof(struct pt_softc), M_DEVBUF,
 M_WAITOK|M_ZERO);
 -   pti-pt_tty = ttymalloc(0);
 +   pti-pt_tty = ttymalloc(PTY_DEF_BAUD);
 ptydevname(minor, pti);
 pt_softc[minor] = pti;
 }
 @@ -235,7 +236,7 @@ ptsopen(dev_t dev, int flag, int devtype
  
 pti = pt_softc[minor(dev)];
 if (!pti-pt_tty) {
 -   tp = pti-pt_tty = ttymalloc(0);
 +   tp = pti-pt_tty = ttymalloc(PTY_DEF_BAUD);
 } else
 tp = pti-pt_tty;
 if ((tp-t_state  TS_ISOPEN) == 0) {
 @@ -413,7 +414,7 @@ ptcopen(dev_t dev, int flag, int devtype
  
 pti = pt_softc[minor(dev)];
 if (!pti-pt_tty) {
 -   tp = pti-pt_tty = ttymalloc(0);
 +   tp = pti-pt_tty = ttymalloc(PTY_DEF_BAUD);
 } else
 tp = pti-pt_tty;
 if (tp-t_oproc)
 Index: net/ppp_tty.c
 ===
 RCS file: /cvs/src/sys/net/ppp_tty.c,v
 retrieving revision 1.33
 diff -u -p -r1.33 ppp_tty.c
 --- net/ppp_tty.c   3 Jun 2015 00:50:09 -   1.33
 +++ net/ppp_tty.c   28 Jun 2015 14:18:16 -
 @@ -163,8 +163,8 @@ struct pool ppp_pkts;
  /* This is a NetBSD-1.0 or later kernel. */
  #define CCOUNT(q)  ((q)-c_cc)
  
 -#define PPP_LOWAT  100 /* Process more output when  LOWAT on queue 
 */
 -#definePPP_HIWAT   400 /* Don't start a new packet if HIWAT 
 on queue */
 +#define PPP_LOWAT  1024/* Process

Re: Pure L2TP client upload performance

2015-06-28 Thread Sergey Ryazanov
2015-06-26 9:20 GMT+03:00 Claudio Jeker cje...@diehard.n-r-g.com:
 On Fri, Jun 26, 2015 at 04:59:32AM +0300, Sergey Ryazanov wrote:
 Hello,

 during building l2tp tunnel with xl2tpd-1.3.1 I was faced with its too
 low  upload  performance.  When  download,  the  speed is 20 mbit/s at
 nearly  100% CPU utilization. CPU is Pentium D 930 3 GHz. When upload,
 the speed is below 2 mbit/s at nearly zero CPU utilization.

 First,  I  examined xl2tpd code and did not find any potential issues.
 Then  I  compiled  it with -pg option and do a quick test with help of
 iperf(1):  4  TCP  flows,  direction  is toward the L2TP server, 2 min
 test.   Then  I run gprof and got pretty strange output:

[skip]

 During  upload  tests, everything looks like if xl2tpd doesn't perform
 any work and stucks somewhere in I/O operation.

 May  be  there are some options, what could be tuned to speedup ppp(4)
 I/O  performance  or  did  I missed something during my tests? I am in
 doubts. Any clues?


 Can you get a ktrace output to figure out what write is doing?
 Could it be that it busy loops with EINTR or EAGAIN?
 It sure smells like something is going on there.


I did make the trace, which shows that write(2) works good, there are no
errors:
# kdump -f ktrace.out-0-tx | grep 'RET   write' | wc -l
   23999
# kdump -f ktrace.out-0-tx | grep 'RET   write.*errno' | wc -l
   0

That was bad news. Let's talk about something good. I finally found a way
to speed up the upload. I got 91 mbit/s, as reported by speedtest.net,
over 100 mbit Ethernet link (at 100% CPU utilization, with the patched
non-SMP kernel).

Looks like the issue is caused by too small size of pty output buffer, and
too small watermarks, which control the pty buffer filling. When pty driver
requests the tty allocation, it passes 0 as baud rate. For any rates, which
is less or equal to 115200, tty driver allocates an output buffer of size
of 1024 byte. And most likely, hardcoded watermarks in the ppp discipline
code are selected according to this buffer size. May be these values were
reasonable for 56k modems, but not for 100 mbit uplink.

Patch for tests is inlined below. All numbers are arbitrary selected values.
I just took first reasonable values and got a positive result, without any
further experiments.

This patch is not suitable for merging, since it just quick and dirty fix.
To solve the issue in more generic way I see several approaches, each of
which has pros and cons:
(a) increase default value (as in this patch);
(b) provide some API (IOCTL) to control buffer size from pppd(8);
(c) make some hack that would reveal pty for high-speed links and increase
their buffer.

Any thoughts?

P.S. If I can get 91 mbit/s of upload rate, then why I get only 20 mbit/s
of download rate on the same machine?

Index: kern/tty_pty.c
===
RCS file: /cvs/src/sys/kern/tty_pty.c,v
retrieving revision 1.70
diff -u -p -r1.70 tty_pty.c
--- kern/tty_pty.c  10 Feb 2015 21:56:10 -  1.70
+++ kern/tty_pty.c  28 Jun 2015 14:18:16 -
@@ -58,6 +58,7 @@
 #include sys/rwlock.h
 
 #define BUFSIZ 100 /* Chunk size iomoved to/from user */
+#define PTY_DEF_BAUD 100
 
 /*
  * pts == /dev/tty[p-zP-T][0-9a-zA-Z]
@@ -192,7 +193,7 @@ check_pty(int minor)
if (!pt_softc[minor]) {
pti = malloc(sizeof(struct pt_softc), M_DEVBUF,
M_WAITOK|M_ZERO);
-   pti-pt_tty = ttymalloc(0);
+   pti-pt_tty = ttymalloc(PTY_DEF_BAUD);
ptydevname(minor, pti);
pt_softc[minor] = pti;
}
@@ -235,7 +236,7 @@ ptsopen(dev_t dev, int flag, int devtype
 
pti = pt_softc[minor(dev)];
if (!pti-pt_tty) {
-   tp = pti-pt_tty = ttymalloc(0);
+   tp = pti-pt_tty = ttymalloc(PTY_DEF_BAUD);
} else
tp = pti-pt_tty;
if ((tp-t_state  TS_ISOPEN) == 0) {
@@ -413,7 +414,7 @@ ptcopen(dev_t dev, int flag, int devtype
 
pti = pt_softc[minor(dev)];
if (!pti-pt_tty) {
-   tp = pti-pt_tty = ttymalloc(0);
+   tp = pti-pt_tty = ttymalloc(PTY_DEF_BAUD);
} else
tp = pti-pt_tty;
if (tp-t_oproc)
Index: net/ppp_tty.c
===
RCS file: /cvs/src/sys/net/ppp_tty.c,v
retrieving revision 1.33
diff -u -p -r1.33 ppp_tty.c
--- net/ppp_tty.c   3 Jun 2015 00:50:09 -   1.33
+++ net/ppp_tty.c   28 Jun 2015 14:18:16 -
@@ -163,8 +163,8 @@ struct pool ppp_pkts;
 /* This is a NetBSD-1.0 or later kernel. */
 #define CCOUNT(q)  ((q)-c_cc)
 
-#define PPP_LOWAT  100 /* Process more output when  LOWAT on queue */
-#definePPP_HIWAT   400 /* Don't start a new packet if HIWAT on 
queue */
+#define PPP_LOWAT  1024/* Process more output when  LOWAT on queue */
+#define PPP_HIWAT  4096/* Don't start a new

Re: Pure L2TP client upload performance

2015-06-26 Thread Sergey Ryazanov
2015-06-26 9:20 GMT+03:00 Claudio Jeker cje...@diehard.n-r-g.com:
 On Fri, Jun 26, 2015 at 04:59:32AM +0300, Sergey Ryazanov wrote:
 Hello,

 during building l2tp tunnel with xl2tpd-1.3.1 I was faced with its too
 low  upload  performance.  When  download,  the  speed is 20 mbit/s at
 nearly  100% CPU utilization. CPU is Pentium D 930 3 GHz. When upload,
 the speed is below 2 mbit/s at nearly zero CPU utilization.

 First,  I  examined xl2tpd code and did not find any potential issues.
 Then  I  compiled  it with -pg option and do a quick test with help of
 iperf(1):  4  TCP  flows,  direction  is toward the L2TP server, 2 min
 test.   Then  I run gprof and got pretty strange output:

 Full output: http://pastebin.com/dm4wz6VK
 granularity: each sample hit covers 4 byte(s) for 11.11% of 0.09 seconds
   %   cumulative   self  self total
  time   seconds   secondscalls  ms/call  ms/call  name
  77.8   0.07 0.0724311 0.00 0.00  write [4]
  22.2   0.09 0.0235897 0.00 0.00  _thread_sys_sendmsg [7]
   0.0   0.09 0.00   109136 0.00 0.00  memset [46]
   0.0   0.09 0.00   107997 0.00 0.00  ___errno [926]
   0.0   0.09 0.0071740 0.00 0.00  read_packet [47]
   0.0   0.09 0.0071726 0.00 0.00  _thread_sys_read [927]
   0.0   0.09 0.0060154 0.00 0.00  
 _thread_sys_gettimeofday [928]
   0.0   0.09 0.0060114 0.00 0.00  process_signal [32]
   0.0   0.09 0.0060113 0.00 0.00  build_fdset [29]
   0.0   0.09 0.0060113 0.00 0.00  process_schedule [26]
   0.0   0.09 0.0060113 0.00 0.00  select [48]
   0.0   0.09 0.0035897 0.00 0.00  udp_xmit [6]

 Another one run also gives something strange:

 Full output: http://pastebin.com/vXvHPuyj
 granularity: each sample hit covers 4 byte(s) for 14.29% of 0.07 seconds
   %   cumulative   self  self total
  time   seconds   secondscalls  ms/call  ms/call  name
  71.4   0.05 0.0524348 0.00 0.00  write [4]
  14.3   0.06 0.0160265 0.00 0.00  select [6]
  14.3   0.07 0.01   10 1.00 1.00  calloc [7]
   0.0   0.07 0.00   109324 0.00 0.00  memset [55]
   0.0   0.07 0.00   108285 0.00 0.00  ___errno [925]
   0.0   0.07 0.0071997 0.00 0.00  read_packet [56]
   0.0   0.07 0.0071980 0.00 0.00  _thread_sys_read [926]
   0.0   0.07 0.0060282 0.00 0.00  
 _thread_sys_gettimeofday [927]
   0.0   0.07 0.0060266 0.00 0.00  process_signal [50]
   0.0   0.07 0.0060265 0.00 0.00  build_fdset [49]
   0.0   0.07 0.0060265 0.00 0.00  process_schedule [57]
   0.0   0.07 0.0036020 0.00 0.00  _thread_sys_sendmsg 
 [928]
   0.0   0.07 0.0036020 0.00 0.00  udp_xmit [58]

 For comparison I changed direction and did a download test:

 Full output: http://pastebin.com/FFF6xGcy
 granularity: each sample hit covers 4 byte(s) for 0.01% of 114.30 seconds
   %   cumulative   self  self total
  time   seconds   secondscalls  ms/call  ms/call  name
  93.7 107.06   107.06   370804 0.29 0.29  write [5]
   1.8 109.08 2.02   370770 0.01 0.01  recvmsg [6]
   1.4 110.67 1.59   370799 0.00 0.00  
 _thread_sys_gettimeofday [8]
   1.1 111.90 1.23   370770 0.00 0.30  handle_packet [4]
   1.0 113.01 1.11   370761 0.00 0.00  add_fcs [9]
   0.7 113.81 0.81   370781 0.00 0.00  select [10]
   0.2 114.03 0.211   210.00 114172.55  network_thread [3]
   0.1 114.14 0.12 mcount [11]
   0.0 114.19 0.05   370781 0.00 0.00  build_fdset [12]
   0.0 114.23 0.04   370771 0.00 0.00  get_call [13]
   0.0 114.27 0.03  1112701 0.00 0.00  memset [14]
   0.0 114.28 0.02   370781 0.00 0.00  process_schedule [7]
   0.0 114.30 0.01   29 0.34 0.34  _thread_sys_sendmsg 
 [20]
   0.0 114.30 0.018 0.62 0.74  inet_ntoa [24]
   0.0 114.30 0.00   370785 0.00 0.00  swaps [110]
   0.0 114.30 0.00   370782 0.00 0.00  process_signal [41]
   0.0 114.30 0.00   370770 0.00 0.00  recycle_buf [111]

 During  upload  tests, everything looks like if xl2tpd doesn't perform
 any work and stucks somewhere in I/O operation.

 May  be  there are some options, what could be tuned to speedup ppp(4)
 I/O  performance  or  did  I missed something during my tests? I am in
 doubts. Any clues?


 Can you get a ktrace output to figure out what write is doing?
 Could it be that it busy loops with EINTR or EAGAIN?
 It sure smells like something is going

Pure L2TP client upload performance

2015-06-25 Thread Sergey Ryazanov
Hello,

during building l2tp tunnel with xl2tpd-1.3.1 I was faced with its too
low  upload  performance.  When  download,  the  speed is 20 mbit/s at
nearly  100% CPU utilization. CPU is Pentium D 930 3 GHz. When upload,
the speed is below 2 mbit/s at nearly zero CPU utilization.

First,  I  examined xl2tpd code and did not find any potential issues.
Then  I  compiled  it with -pg option and do a quick test with help of
iperf(1):  4  TCP  flows,  direction  is toward the L2TP server, 2 min
test.   Then  I run gprof and got pretty strange output:

Full output: http://pastebin.com/dm4wz6VK
granularity: each sample hit covers 4 byte(s) for 11.11% of 0.09 seconds
  %   cumulative   self  self total
 time   seconds   secondscalls  ms/call  ms/call  name
 77.8   0.07 0.0724311 0.00 0.00  write [4]
 22.2   0.09 0.0235897 0.00 0.00  _thread_sys_sendmsg [7]
  0.0   0.09 0.00   109136 0.00 0.00  memset [46]
  0.0   0.09 0.00   107997 0.00 0.00  ___errno [926]
  0.0   0.09 0.0071740 0.00 0.00  read_packet [47]
  0.0   0.09 0.0071726 0.00 0.00  _thread_sys_read [927]
  0.0   0.09 0.0060154 0.00 0.00  _thread_sys_gettimeofday 
[928]
  0.0   0.09 0.0060114 0.00 0.00  process_signal [32]
  0.0   0.09 0.0060113 0.00 0.00  build_fdset [29]
  0.0   0.09 0.0060113 0.00 0.00  process_schedule [26]
  0.0   0.09 0.0060113 0.00 0.00  select [48]
  0.0   0.09 0.0035897 0.00 0.00  udp_xmit [6]

Another one run also gives something strange:

Full output: http://pastebin.com/vXvHPuyj
granularity: each sample hit covers 4 byte(s) for 14.29% of 0.07 seconds
  %   cumulative   self  self total
 time   seconds   secondscalls  ms/call  ms/call  name
 71.4   0.05 0.0524348 0.00 0.00  write [4]
 14.3   0.06 0.0160265 0.00 0.00  select [6]
 14.3   0.07 0.01   10 1.00 1.00  calloc [7]
  0.0   0.07 0.00   109324 0.00 0.00  memset [55]
  0.0   0.07 0.00   108285 0.00 0.00  ___errno [925]
  0.0   0.07 0.0071997 0.00 0.00  read_packet [56]
  0.0   0.07 0.0071980 0.00 0.00  _thread_sys_read [926]
  0.0   0.07 0.0060282 0.00 0.00  _thread_sys_gettimeofday 
[927]
  0.0   0.07 0.0060266 0.00 0.00  process_signal [50]
  0.0   0.07 0.0060265 0.00 0.00  build_fdset [49]
  0.0   0.07 0.0060265 0.00 0.00  process_schedule [57]
  0.0   0.07 0.0036020 0.00 0.00  _thread_sys_sendmsg [928]
  0.0   0.07 0.0036020 0.00 0.00  udp_xmit [58]

For comparison I changed direction and did a download test:

Full output: http://pastebin.com/FFF6xGcy
granularity: each sample hit covers 4 byte(s) for 0.01% of 114.30 seconds
  %   cumulative   self  self total
 time   seconds   secondscalls  ms/call  ms/call  name
 93.7 107.06   107.06   370804 0.29 0.29  write [5]
  1.8 109.08 2.02   370770 0.01 0.01  recvmsg [6]
  1.4 110.67 1.59   370799 0.00 0.00  _thread_sys_gettimeofday 
[8]
  1.1 111.90 1.23   370770 0.00 0.30  handle_packet [4]
  1.0 113.01 1.11   370761 0.00 0.00  add_fcs [9]
  0.7 113.81 0.81   370781 0.00 0.00  select [10]
  0.2 114.03 0.211   210.00 114172.55  network_thread [3]
  0.1 114.14 0.12 mcount [11]
  0.0 114.19 0.05   370781 0.00 0.00  build_fdset [12]
  0.0 114.23 0.04   370771 0.00 0.00  get_call [13]
  0.0 114.27 0.03  1112701 0.00 0.00  memset [14]
  0.0 114.28 0.02   370781 0.00 0.00  process_schedule [7]
  0.0 114.30 0.01   29 0.34 0.34  _thread_sys_sendmsg [20]
  0.0 114.30 0.018 0.62 0.74  inet_ntoa [24]
  0.0 114.30 0.00   370785 0.00 0.00  swaps [110]
  0.0 114.30 0.00   370782 0.00 0.00  process_signal [41]
  0.0 114.30 0.00   370770 0.00 0.00  recycle_buf [111]

During  upload  tests, everything looks like if xl2tpd doesn't perform
any work and stucks somewhere in I/O operation.

May  be  there are some options, what could be tuned to speedup ppp(4)
I/O  performance  or  did  I missed something during my tests? I am in
doubts. Any clues?

-- 
Sergey



patch: pppd: fix crash in LCP reject codepath

2015-06-12 Thread Sergey Ryazanov
pppd(8)  creates  Reject  message  by  moving  with memcpy(3) rejected
option  to  left  in  buffer.  If  moving distance is less then option
length  than it falls in coping between overlapping regions case. What
leads to crash.

The  following  patch  fixes  this  issue  by  replacing  memcpy(3) by
memmove(3).

Index: pppd.h
===
RCS file: /cvs/src/usr.sbin/pppd/pppd.h,v
retrieving revision 1.18
diff -u -p -r1.18 pppd.h
--- pppd.h  16 Jan 2015 06:40:19 -  1.18
+++ pppd.h  12 Jun 2015 12:11:14 -
@@ -402,6 +402,7 @@ extern struct option_info devnam_info;
 #define UNTIMEOUT(r, f)untimeout((r), (f))
 
 #define BCOPY(s, d, l) memcpy(d, s, l)
+#define BMOVE(s, d, l) memmove(d, s, l)
 #define BZERO(s, n)memset(s, 0, n)
 #define EXIT(u)quit()
 
Index: lcp.c
===
RCS file: /cvs/src/usr.sbin/pppd/lcp.c,v
retrieving revision 1.11
diff -u -p -r1.11 lcp.c
--- lcp.c   15 Jan 2015 23:19:48 -  1.11
+++ lcp.c   12 Jun 2015 12:11:14 -
@@ -1441,7 +1441,7 @@ endswitch:
if (orc == CONFREJ) {   /* Reject this CI */
rc = CONFREJ;
if (cip != rejp)/* Need to move rejected CI? */
-   BCOPY(cip, rejp, cilen); /* Move it */
+   BMOVE(cip, rejp, cilen); /* Move it (NB: overlapped regions) */
INCPTR(cilen, rejp);/* Update output pointer */
}
 }
-- 
Sergey



Re: patch: pppd: fix crash in LCP reject codepath

2015-06-12 Thread Sergey Ryazanov
Friday, June 12, 2015, 4:09:09 PM, you wrote:
 pppd(8)  creates  Reject  message  by  moving  with memcpy(3) rejected
 option  to  left  in  buffer.  If  moving distance is less then option
 length  than it falls in coping between overlapping regions case. What
 leads to crash.

 The  following  patch  fixes  this  issue  by  replacing  memcpy(3) by
 memmove(3).

Sorry,  looks  like  my  email client replace all tabs by whitespaces.
Please find correct patch in the attachment.

-- 
Sergey

pppd-fix-crash-in-lcp-reject.patch
Description: Binary data