Re: RFC: L2TPv3 interface
Hi, On 2017/02/07 14:01, Kengo NAKAHARA wrote: > On 2017/01/20 21:26, Kengo NAKAHARA wrote: >> At first, here is updated patches. >> >> http://netbsd.org/~knakahara/if-l2tp-2/01-accept-ifname-include-digit.patch >>http://netbsd.org/~knakahara/if-l2tp-2/02-if-l2tp.patch > > I rebase and add some fixes. Here is updated patch set and unified patch. > - patch set > http://netbsd.org/~knakahara/if-l2tp-3/if-l2tp-3.tgz > - unified patch > http://netbsd.org/~knakahara/if-l2tp-3/if-l2tp-3.patch > > Could you comment this patch set? If there is no objection, I will commit > this patch set after a few days or weeks. I committed it. Thanks, -- // Internet Initiative Japan Inc. Device Engineering Section, IoT Platform Development Department, Network Division, Technology Unit Kengo NAKAHARA
Re: RFC: L2TPv3 interface
Hi, On 2017/01/20 21:26, Kengo NAKAHARA wrote: > At first, here is updated patches. >http://netbsd.org/~knakahara/if-l2tp-2/01-accept-ifname-include-digit.patch >http://netbsd.org/~knakahara/if-l2tp-2/02-if-l2tp.patch I rebase and add some fixes. Here is updated patch set and unified patch. - patch set http://netbsd.org/~knakahara/if-l2tp-3/if-l2tp-3.tgz - unified patch http://netbsd.org/~knakahara/if-l2tp-3/if-l2tp-3.patch Could you comment this patch set? If there is no objection, I will commit this patch set after a few days or weeks. Thanks, -- // Internet Initiative Japan Inc. Device Engineering Section, IoT Platform Development Department, Network Division, Technology Unit Kengo NAKAHARA
Re: RFC: L2TPv3 interface
Hi, On 2017/01/20 21:26, Kengo NAKAHARA wrote: > On 2017/01/20 0:38, Taylor R Campbell wrote: >>Date: Thu, 19 Jan 2017 17:58:17 +0900 >>From: Kengo NAKAHARA >>+/* >>+ * l2tp_variant update API. >>+ * >>+ * Assumption: >>+ * reader side dereferences sc->l2tp_var in reader critical section only, >>+ * that is, all of reader sides do not reader the sc->l2tp_var after >>+ * pserialize_perform(). >>+ */ >>+static void >>+l2tp_variant_update(struct l2tp_softc *sc, struct l2tp_variant *nvar) >>+{ >>+ struct ifnet *ifp = &sc->l2tp_ec.ec_if; >>+ struct l2tp_variant *ovar = sc->l2tp_var; >>+ >>+ KASSERT(mutex_owned(&sc->l2tp_lock)); >>+ >>+ membar_producer(); >>+ atomic_swap_ptr(&sc->l2tp_var, nvar); >>+ pserialize_perform(l2tp_psz); >>+ psref_target_destroy(&ovar->lv_psref, lv_psref_class); >> >> No need for atomic_swap_ptr. Just >> >> sc->l2tp_var = nvar; >> >> is enough. Nobody else can write to it because we hold the lock. > > Between writer and writer, it is correct. However, between writer and > reader, I think atomic_swap_ptr is required to prevent reader's load > before writer's store done. Is this correct? Sorry, I was wrong. Reader has nothing to do with atomic_ops. So, As you said, atomic_swap_ptr is not required here. I will fix it. Thanks, -- // Internet Initiative Japan Inc. Device Engineering Section, IoT Platform Development Department, Network Division, Technology Unit Kengo NAKAHARA
Re: RFC: L2TPv3 interface
On Fri, Jan 20, 2017 at 09:26:52PM +0900, Kengo NAKAHARA wrote: > On 2017/01/20 0:38, Taylor R Campbell wrote: > >Date: Thu, 19 Jan 2017 17:58:17 +0900 > >From: Kengo NAKAHARA > > A few little comments: > > > >diff --git a/sys/net/if.c b/sys/net/if.c > >index 2386af3..ba63266 100644 > >--- a/sys/net/if.c > >+++ b/sys/net/if.c > >@@ -1599,7 +1613,7 @@ if_clone_lookup(const char *name, int *unitp) > >strcpy(ifname, "if_"); > >/* separate interface name from unit */ > >for (dp = ifname + 3, cp = name; cp - name < IFNAMSIZ && > >- *cp && (*cp < '0' || *cp > '9');) > >+ *cp && !if_is_unit(cp);) > >*dp++ = *cp++; > > > > This changes the generic syntax interface names, perhaps to allow the > > `2' in `l2tp', although since this loop skips over the first three > > octets that doesn't seem to be necessary. Either way, I don't have a > > problem with this, but it should be done in a separate change. > > I see. But sorry, I want to postpone the fix to reduce unnecessary > skip... As a first step, I separate this changes and will commit first. BTW, a proper fix should be looking backwards from the end of the string and not forward. Joerg
Re: RFC: L2TPv3 interface
Hi riastradh@n.o, Thank you for your detailed review! At first, here is updated patches. http://netbsd.org/~knakahara/if-l2tp-2/01-accept-ifname-include-digit.patch http://netbsd.org/~knakahara/if-l2tp-2/02-if-l2tp.patch And then, each response is below. On 2017/01/20 0:38, Taylor R Campbell wrote: >Date: Thu, 19 Jan 2017 17:58:17 +0900 >From: Kengo NAKAHARA > A few little comments: > >diff --git a/sys/net/if.c b/sys/net/if.c >index 2386af3..ba63266 100644 >--- a/sys/net/if.c >+++ b/sys/net/if.c >@@ -1599,7 +1613,7 @@ if_clone_lookup(const char *name, int *unitp) >strcpy(ifname, "if_"); >/* separate interface name from unit */ >for (dp = ifname + 3, cp = name; cp - name < IFNAMSIZ && >- *cp && (*cp < '0' || *cp > '9');) >+ *cp && !if_is_unit(cp);) >*dp++ = *cp++; > > This changes the generic syntax interface names, perhaps to allow the > `2' in `l2tp', although since this loop skips over the first three > octets that doesn't seem to be necessary. Either way, I don't have a > problem with this, but it should be done in a separate change. I see. But sorry, I want to postpone the fix to reduce unnecessary skip... As a first step, I separate this changes and will commit first. >diff --git a/sys/net/if_l2tp.c b/sys/net/if_l2tp.c >new file mode 100644 >index 000..dda8bbd >--- /dev/null >+++ b/sys/net/if_l2tp.c >@@ -0,0 +1,1541 @@ >[...] >+/* >+ * l2tp global variable definitions >+ */ >+LIST_HEAD(l2tp_sclist, l2tp_softc); >+static struct l2tp_sclist l2tp_softc_list; >+kmutex_t l2tp_list_lock; >+ >+#if !defined(L2TP_ID_HASH_SIZE) >+#define L2TP_ID_HASH_SIZE 64 >+#endif >+static u_long l2tp_id_hash_mask; >+ >+kmutex_t l2tp_hash_lock; >+static struct pslist_head *l2tp_hashed_list = NULL; > > Consider putting related global state into cacheline-aligned structs? Oh, I forgot it. I should put them into cacheline-aligned structs. In addition, I remove l2tp_id_hash_mask variable and use L2TP_ID_HASH_SIZE to avoid holding lock in fast-path (l2tp_lookup_session_ref() => id_hash_func()). > static struct { > kmutex_t lock; > struct l2tp_sclistlist; > } l2tp_softc __cacheline_aligned; > > static struct { > kmutex_t lock; > struct pslist_head*list; > unsigned long mask; > } l2tp_hash __cacheline_aligned; > >+pserialize_t l2tp_psz; >+struct psref_class *lv_psref_class __read_mostly; > > __read_mostly for l2tp_psz? Yes, I add it. >+static int >+l2tpdetach(void) >+{ >+ int error; >+ >+ if (!LIST_EMPTY(&l2tp_softc_list)) >+ return EBUSY; > > Need lock here? Need to first set flag preventing new creation? > > mutex_enter(&l2tp_softc.lock); > KASSERT(!l2tp_softc.dying); > l2tp_softc.detaching = true; > if (!LIST_EMPTY(&l2tp_softc.list)) { > l2tp_softc.detaching = false; > mutex_exit(&l2tp_softc.lock); > return EBUSY; > } > mutex_exit(&l2tp_softc.lock); > > Anyone trying to add to l2tp_softc.list must also check > l2tp_softc.detaching before proceeding. You are right. Hmm..., it's seems there are same problems in other module'd interfaces such as pppoe(4), gre(4), and so on. I think module framework could fix this problem, so I will ask pgoyette@n.o and christos@n.o if they have any idea later. >+static int >+l2tp_clone_destroy(struct ifnet *ifp) >+{ >+ struct l2tp_softc *sc = (void *) ifp; > > Use container_of here: > > struct l2tp_softc *sc = container_of(ifp, struct l2tp_softc, > l2tp_ec.ec_if); > > No functional difference, but the compiler type-checks it. I use container_of here and similar codes. >+void >+l2tp_input(struct mbuf *m, struct ifnet *ifp) >+{ >+ >+ KASSERT(ifp != NULL); >+ >+ if (0 == (mtod(m, u_long) & 0x03)) { >+ /* copy and align head of payload */ >+ struct mbuf *m_head; >+ int copy_length; >+ >+#define L2TP_COPY_LENGTH 60 >+#define L2TP_LINK_HDR_ROOM (MHLEN - L2TP_COPY_LENGTH - 4/*round4(2)*/) >+ >+ if (m->m_pkthdr.len < L2TP_COPY_LENGTH) { >+ copy_length = m->m_pkthdr.len; >+ } else { >+ copy_length = L2TP_COPY_LENGTH; >+ } >+ >+ if (m->m_len < copy_length) { >+ m = m_pullup(m, copy_length); >+ if (m == NULL) >+ return; >+ } >+ >+ MGETHDR(m_head, M_DONTWAIT, MT_HEADER); >+ if (m_head == NULL) { >+ m_freem(m); >+ return; >+
Re: RFC: L2TPv3 interface
Date: Thu, 19 Jan 2017 17:58:17 +0900 From: Kengo NAKAHARA My co-workers implemented L2TPv3(RFC3931) interface for old version NetBSD. And then, I port the inteface to NetBSD-current and MP-ify. Here is the patch. http://netbsd.org/~knakahara/if-l2tp/if-l2tp.patch Cool! A few little comments: diff --git a/sys/net/if.c b/sys/net/if.c index 2386af3..ba63266 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -1599,7 +1613,7 @@ if_clone_lookup(const char *name, int *unitp) strcpy(ifname, "if_"); /* separate interface name from unit */ for (dp = ifname + 3, cp = name; cp - name < IFNAMSIZ && - *cp && (*cp < '0' || *cp > '9');) + *cp && !if_is_unit(cp);) *dp++ = *cp++; This changes the generic syntax interface names, perhaps to allow the `2' in `l2tp', although since this loop skips over the first three octets that doesn't seem to be necessary. Either way, I don't have a problem with this, but it should be done in a separate change. diff --git a/sys/net/if_l2tp.c b/sys/net/if_l2tp.c new file mode 100644 index 000..dda8bbd --- /dev/null +++ b/sys/net/if_l2tp.c @@ -0,0 +1,1541 @@ [...] +/* + * l2tp global variable definitions + */ +LIST_HEAD(l2tp_sclist, l2tp_softc); +static struct l2tp_sclist l2tp_softc_list; +kmutex_t l2tp_list_lock; + +#if !defined(L2TP_ID_HASH_SIZE) +#define L2TP_ID_HASH_SIZE 64 +#endif +static u_long l2tp_id_hash_mask; + +kmutex_t l2tp_hash_lock; +static struct pslist_head *l2tp_hashed_list = NULL; Consider putting related global state into cacheline-aligned structs? static struct { kmutex_tlock; struct l2tp_sclist list; } l2tp_softc __cacheline_aligned; static struct { kmutex_tlock; struct pslist_head *list; unsigned long mask; } l2tp_hash __cacheline_aligned; +pserialize_t l2tp_psz; +struct psref_class *lv_psref_class __read_mostly; __read_mostly for l2tp_psz? +static int +l2tpdetach(void) +{ + int error; + + if (!LIST_EMPTY(&l2tp_softc_list)) + return EBUSY; Need lock here? Need to first set flag preventing new creation? mutex_enter(&l2tp_softc.lock); KASSERT(!l2tp_softc.dying); l2tp_softc.detaching = true; if (!LIST_EMPTY(&l2tp_softc.list)) { l2tp_softc.detaching = false; mutex_exit(&l2tp_softc.lock); return EBUSY; } mutex_exit(&l2tp_softc.lock); Anyone trying to add to l2tp_softc.list must also check l2tp_softc.detaching before proceeding. +static int +l2tp_clone_destroy(struct ifnet *ifp) +{ + struct l2tp_softc *sc = (void *) ifp; Use container_of here: struct l2tp_softc *sc = container_of(ifp, struct l2tp_softc, l2tp_ec.ec_if); No functional difference, but the compiler type-checks it. +static int +l2tp_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, +const struct rtentry *rt) +{ + struct l2tp_softc *sc = (struct l2tp_softc*)ifp; container_of +void +l2tp_input(struct mbuf *m, struct ifnet *ifp) +{ + + KASSERT(ifp != NULL); + + if (0 == (mtod(m, u_long) & 0x03)) { + /* copy and align head of payload */ + struct mbuf *m_head; + int copy_length; + +#define L2TP_COPY_LENGTH 60 +#define L2TP_LINK_HDR_ROOM (MHLEN - L2TP_COPY_LENGTH - 4/*round4(2)*/) + + if (m->m_pkthdr.len < L2TP_COPY_LENGTH) { + copy_length = m->m_pkthdr.len; + } else { + copy_length = L2TP_COPY_LENGTH; + } + + if (m->m_len < copy_length) { + m = m_pullup(m, copy_length); + if (m == NULL) + return; + } + + MGETHDR(m_head, M_DONTWAIT, MT_HEADER); + if (m_head == NULL) { + m_freem(m); + return; + } + M_COPY_PKTHDR(m_head, m); + + m_head->m_data += 2 /* align */ + L2TP_LINK_HDR_ROOM; + memcpy(m_head->m_data, m->m_data, copy_length); + m_head->m_len = copy_length; + m->m_data += copy_length; + m->m_len -= copy_length; + + /* construct chain */ + if (m->m_len == 0) { + m_head->m_next = m_free(m); /* not m_freem */ + } else { + /* +* copyed mtag in previous call M_COPY_PKTHDR +* but don't delete mtag in case cutt of M_PKTHDR flag +*/ + m
Re: RFC: L2TPv3 interface
In article <93c56002-6eb8-0694-3b68-20805ed07...@iij.ad.jp>, Kengo NAKAHARA wrote: >Hi, > >My co-workers implemented L2TPv3(RFC3931) interface for old version NetBSD. >And then, I port the inteface to NetBSD-current and MP-ify. Here is the patch. >http://netbsd.org/~knakahara/if-l2tp/if-l2tp.patch > >The L2TPv3 interface implementation is named l2tp(4), which can send/receive >L2TPv3 data packet and control packet. Above patch include ifconfig(8) >extension, so we can create L2TPv3 tunnel between hostA and hostB as below. LGTM! christos
RFC: L2TPv3 interface
Hi, My co-workers implemented L2TPv3(RFC3931) interface for old version NetBSD. And then, I port the inteface to NetBSD-current and MP-ify. Here is the patch. http://netbsd.org/~knakahara/if-l2tp/if-l2tp.patch The L2TPv3 interface implementation is named l2tp(4), which can send/receive L2TPv3 data packet and control packet. Above patch include ifconfig(8) extension, so we can create L2TPv3 tunnel between hostA and hostB as below. == host A == # ifconfig wm0 inet 192.168.0.1/24 # ifconfig l2tp0 create # ifconfig l2tp0 tunnel 192.168.0.1 192.168.0.2 # ifconfig l2tp0 session 1234 4321 # ifconfig bridge0 create # brconfig bridge0 add wm1 # brconfig bridge0 add l2tp0 # ifconfig l2tp0 up # ifconfig wm1 up # ifconfig bridge0 up == host A == == host B == # ifconfig l2tp0 create # ifconfig l2tp0 tunnel 192.168.0.2 192.168.0.1 # ifconfig l2tp0 session 4321 1234 # ifconfig bridge0 create # brconfig bridge0 add wm1 # brconfig bridge0 add l2tp0 # ifconfig l2tp0 up # ifconfig wm1 up # ifconfig bridge0 up == host B == As l2tp(4) interface can send/receive L2TPv3 control packet, we can implement userland daemon which manage sessions, that is, authentication, keepalive, and so on. That's future work. Could you comment this patch? Thanks, -- // Internet Initiative Japan Inc. Device Engineering Section, IoT Platform Development Department, Network Division, Technology Unit Kengo NAKAHARA