Re: Stop calling IPsec and pf under splnet

2013-07-31 Thread David Hill
On Tue, Jul 30, 2013 at 11:30:51AM +0200, Martin Pieuchot wrote:
 On 12/07/13(Fri) 11:35, Mike Belopuhov wrote:
  Hi,
  
  As it was pointed out by dhill there are some rogue splnets in
  the tcp_input that shouldn't be there really.  The only reason
  they're still there is to match overzealous splnets in bridge_
  broadcast.  bridge_ifenqueue is the only function call in there
  that requires splnet protection since it's dealing with send
  queues.  Narrowing the range of the splnet protection allows us
  to remove all splnet protection of the IPsec SPD and TDB code.
  This as well removes the only pf_test call done under IPL_NET.
  
  Below are essentially two diffs that are rather hard to separate.
  I've tested the diff with the gif-to-ethernet IPsec bridge but
  some additional IPsec and bridge testing won't hurt.
  
  mpi@ has provided some feedback already, so I'm really looking
  for OK's on this.
 
 ok mpi@

been running this on i386 for a while with plenty of ipsec traffic.  no
issues.

 
  diff --git sys/net/if_bridge.c sys/net/if_bridge.c
  index 41d7b67..0ca2710 100644
  --- sys/net/if_bridge.c
  +++ sys/net/if_bridge.c
  @@ -969,12 +969,10 @@ bridge_output(struct ifnet *ifp, struct mbuf *m, 
  struct sockaddr *sa,
  return (ENOBUFS);
  }
  eh = mtod(m, struct ether_header *);
  dst = (struct ether_addr *)eh-ether_dhost[0];
   
  -   s = splnet();
  -
  /*
   * If bridge is down, but original output interface is up,
   * go ahead and send out that interface.  Otherwise the packet
   * is dropped below.
   */
  @@ -1007,11 +1005,10 @@ bridge_output(struct ifnet *ifp, struct mbuf *m, 
  struct sockaddr *sa,
   */
  if ((mtag = m_tag_find(m, PACKET_TAG_IPSEC_OUT_CRYPTO_NEEDED,
  NULL)) != NULL) {
  ipsp_skipcrypto_unmark((struct tdb_ident *)(mtag + 1));
  m_freem(m);
  -   splx(s);
  return (0);
  }
   #endif /* IPSEC */
  bridge_span(sc, NULL, m);
   
  @@ -1074,22 +1071,24 @@ bridge_output(struct ifnet *ifp, struct mbuf *m, 
  struct sockaddr *sa,
  m1-m_pkthdr.len = len;
  }
  mc = m1;
  }
   
  +   s = splnet();
  error = bridge_ifenqueue(sc, dst_if, mc);
  +   splx(s);
  if (error)
  continue;
  }
  if (!used)
  m_freem(m);
  -   splx(s);
  return (0);
  }
   
   sendunicast:
  bridge_span(sc, NULL, m);
  +   s = splnet();
  if ((dst_if-if_flags  IFF_RUNNING) == 0) {
  m_freem(m);
  splx(s);
  return (ENETDOWN);
  }
  @@ -1251,13 +1250,11 @@ bridgeintr_frame(struct bridge_softc *sc, struct 
  mbuf *m)
   * If the packet is a multicast or broadcast OR if we don't
   * know any better, forward it to all interfaces.
   */
  if ((m-m_flags  (M_BCAST | M_MCAST)) || dst_if == NULL) {
  sc-sc_if.if_imcasts++;
  -   s = splnet();
  bridge_broadcast(sc, src_if, eh, m);
  -   splx(s);
  return;
  }
   
  /*
   * At this point, we're dealing with a unicast frame going to a
  @@ -1496,13 +1493,11 @@ bridge_broadcast(struct bridge_softc *sc, struct 
  ifnet *ifp,
   struct ether_header *eh, struct mbuf *m)
   {
  struct bridge_iflist *p;
  struct mbuf *mc;
  struct ifnet *dst_if;
  -   int len, used = 0;
  -
  -   splassert(IPL_NET);
  +   int len, s, used = 0;
   
  TAILQ_FOREACH(p, sc-sc_iflist, next) {
  /*
   * Don't retransmit out of the same interface where
   * the packet was received from.
  @@ -1587,11 +1582,13 @@ bridge_broadcast(struct bridge_softc *sc, struct 
  ifnet *ifp,
  len += ETHER_VLAN_ENCAP_LEN;
   #endif
  if ((len - ETHER_HDR_LEN)  dst_if-if_mtu)
  bridge_fragment(sc, dst_if, eh, mc);
  else {
  +   s = splnet();
  bridge_ifenqueue(sc, dst_if, mc);
  +   splx(s);
  }
  }
   
  if (!used)
  m_freem(m);
  @@ -1643,11 +1640,11 @@ bridge_span(struct bridge_softc *sc, struct 
  ether_header *eh,
   struct mbuf *morig)
   {
  struct bridge_iflist *p;
  struct ifnet *ifp;
  struct mbuf *mc, *m;
  -   int error;
  +   int s, error;
   
  if (TAILQ_EMPTY(sc-sc_spanlist))
  return;
   
  m = m_copym2(morig, 0, M_COPYALL, M_NOWAIT);
  @@ -1679,11 +1676,13 @@ bridge_span(struct bridge_softc *sc, struct 
  ether_header *eh,
  if (mc == NULL) {
  sc-sc_if.if_oerrors++;
  continue;
  }
   
  +   s = 

Re: Stop calling IPsec and pf under splnet

2013-07-30 Thread Martin Pieuchot
On 12/07/13(Fri) 11:35, Mike Belopuhov wrote:
 Hi,
 
 As it was pointed out by dhill there are some rogue splnets in
 the tcp_input that shouldn't be there really.  The only reason
 they're still there is to match overzealous splnets in bridge_
 broadcast.  bridge_ifenqueue is the only function call in there
 that requires splnet protection since it's dealing with send
 queues.  Narrowing the range of the splnet protection allows us
 to remove all splnet protection of the IPsec SPD and TDB code.
 This as well removes the only pf_test call done under IPL_NET.
 
 Below are essentially two diffs that are rather hard to separate.
 I've tested the diff with the gif-to-ethernet IPsec bridge but
 some additional IPsec and bridge testing won't hurt.
 
 mpi@ has provided some feedback already, so I'm really looking
 for OK's on this.

ok mpi@

 diff --git sys/net/if_bridge.c sys/net/if_bridge.c
 index 41d7b67..0ca2710 100644
 --- sys/net/if_bridge.c
 +++ sys/net/if_bridge.c
 @@ -969,12 +969,10 @@ bridge_output(struct ifnet *ifp, struct mbuf *m, struct 
 sockaddr *sa,
   return (ENOBUFS);
   }
   eh = mtod(m, struct ether_header *);
   dst = (struct ether_addr *)eh-ether_dhost[0];
  
 - s = splnet();
 -
   /*
* If bridge is down, but original output interface is up,
* go ahead and send out that interface.  Otherwise the packet
* is dropped below.
*/
 @@ -1007,11 +1005,10 @@ bridge_output(struct ifnet *ifp, struct mbuf *m, 
 struct sockaddr *sa,
*/
   if ((mtag = m_tag_find(m, PACKET_TAG_IPSEC_OUT_CRYPTO_NEEDED,
   NULL)) != NULL) {
   ipsp_skipcrypto_unmark((struct tdb_ident *)(mtag + 1));
   m_freem(m);
 - splx(s);
   return (0);
   }
  #endif /* IPSEC */
   bridge_span(sc, NULL, m);
  
 @@ -1074,22 +1071,24 @@ bridge_output(struct ifnet *ifp, struct mbuf *m, 
 struct sockaddr *sa,
   m1-m_pkthdr.len = len;
   }
   mc = m1;
   }
  
 + s = splnet();
   error = bridge_ifenqueue(sc, dst_if, mc);
 + splx(s);
   if (error)
   continue;
   }
   if (!used)
   m_freem(m);
 - splx(s);
   return (0);
   }
  
  sendunicast:
   bridge_span(sc, NULL, m);
 + s = splnet();
   if ((dst_if-if_flags  IFF_RUNNING) == 0) {
   m_freem(m);
   splx(s);
   return (ENETDOWN);
   }
 @@ -1251,13 +1250,11 @@ bridgeintr_frame(struct bridge_softc *sc, struct mbuf 
 *m)
* If the packet is a multicast or broadcast OR if we don't
* know any better, forward it to all interfaces.
*/
   if ((m-m_flags  (M_BCAST | M_MCAST)) || dst_if == NULL) {
   sc-sc_if.if_imcasts++;
 - s = splnet();
   bridge_broadcast(sc, src_if, eh, m);
 - splx(s);
   return;
   }
  
   /*
* At this point, we're dealing with a unicast frame going to a
 @@ -1496,13 +1493,11 @@ bridge_broadcast(struct bridge_softc *sc, struct 
 ifnet *ifp,
  struct ether_header *eh, struct mbuf *m)
  {
   struct bridge_iflist *p;
   struct mbuf *mc;
   struct ifnet *dst_if;
 - int len, used = 0;
 -
 - splassert(IPL_NET);
 + int len, s, used = 0;
  
   TAILQ_FOREACH(p, sc-sc_iflist, next) {
   /*
* Don't retransmit out of the same interface where
* the packet was received from.
 @@ -1587,11 +1582,13 @@ bridge_broadcast(struct bridge_softc *sc, struct 
 ifnet *ifp,
   len += ETHER_VLAN_ENCAP_LEN;
  #endif
   if ((len - ETHER_HDR_LEN)  dst_if-if_mtu)
   bridge_fragment(sc, dst_if, eh, mc);
   else {
 + s = splnet();
   bridge_ifenqueue(sc, dst_if, mc);
 + splx(s);
   }
   }
  
   if (!used)
   m_freem(m);
 @@ -1643,11 +1640,11 @@ bridge_span(struct bridge_softc *sc, struct 
 ether_header *eh,
  struct mbuf *morig)
  {
   struct bridge_iflist *p;
   struct ifnet *ifp;
   struct mbuf *mc, *m;
 - int error;
 + int s, error;
  
   if (TAILQ_EMPTY(sc-sc_spanlist))
   return;
  
   m = m_copym2(morig, 0, M_COPYALL, M_NOWAIT);
 @@ -1679,11 +1676,13 @@ bridge_span(struct bridge_softc *sc, struct 
 ether_header *eh,
   if (mc == NULL) {
   sc-sc_if.if_oerrors++;
   continue;
   }
  
 + s = splnet();
   error = bridge_ifenqueue(sc, ifp, mc);
 + splx(s);
   if (error)
   

Stop calling IPsec and pf under splnet

2013-07-12 Thread Mike Belopuhov
Hi,

As it was pointed out by dhill there are some rogue splnets in
the tcp_input that shouldn't be there really.  The only reason
they're still there is to match overzealous splnets in bridge_
broadcast.  bridge_ifenqueue is the only function call in there
that requires splnet protection since it's dealing with send
queues.  Narrowing the range of the splnet protection allows us
to remove all splnet protection of the IPsec SPD and TDB code.
This as well removes the only pf_test call done under IPL_NET.

Below are essentially two diffs that are rather hard to separate.
I've tested the diff with the gif-to-ethernet IPsec bridge but
some additional IPsec and bridge testing won't hurt.

mpi@ has provided some feedback already, so I'm really looking
for OK's on this.

diff --git sys/net/if_bridge.c sys/net/if_bridge.c
index 41d7b67..0ca2710 100644
--- sys/net/if_bridge.c
+++ sys/net/if_bridge.c
@@ -969,12 +969,10 @@ bridge_output(struct ifnet *ifp, struct mbuf *m, struct 
sockaddr *sa,
return (ENOBUFS);
}
eh = mtod(m, struct ether_header *);
dst = (struct ether_addr *)eh-ether_dhost[0];
 
-   s = splnet();
-
/*
 * If bridge is down, but original output interface is up,
 * go ahead and send out that interface.  Otherwise the packet
 * is dropped below.
 */
@@ -1007,11 +1005,10 @@ bridge_output(struct ifnet *ifp, struct mbuf *m, struct 
sockaddr *sa,
 */
if ((mtag = m_tag_find(m, PACKET_TAG_IPSEC_OUT_CRYPTO_NEEDED,
NULL)) != NULL) {
ipsp_skipcrypto_unmark((struct tdb_ident *)(mtag + 1));
m_freem(m);
-   splx(s);
return (0);
}
 #endif /* IPSEC */
bridge_span(sc, NULL, m);
 
@@ -1074,22 +1071,24 @@ bridge_output(struct ifnet *ifp, struct mbuf *m, struct 
sockaddr *sa,
m1-m_pkthdr.len = len;
}
mc = m1;
}
 
+   s = splnet();
error = bridge_ifenqueue(sc, dst_if, mc);
+   splx(s);
if (error)
continue;
}
if (!used)
m_freem(m);
-   splx(s);
return (0);
}
 
 sendunicast:
bridge_span(sc, NULL, m);
+   s = splnet();
if ((dst_if-if_flags  IFF_RUNNING) == 0) {
m_freem(m);
splx(s);
return (ENETDOWN);
}
@@ -1251,13 +1250,11 @@ bridgeintr_frame(struct bridge_softc *sc, struct mbuf 
*m)
 * If the packet is a multicast or broadcast OR if we don't
 * know any better, forward it to all interfaces.
 */
if ((m-m_flags  (M_BCAST | M_MCAST)) || dst_if == NULL) {
sc-sc_if.if_imcasts++;
-   s = splnet();
bridge_broadcast(sc, src_if, eh, m);
-   splx(s);
return;
}
 
/*
 * At this point, we're dealing with a unicast frame going to a
@@ -1496,13 +1493,11 @@ bridge_broadcast(struct bridge_softc *sc, struct ifnet 
*ifp,
 struct ether_header *eh, struct mbuf *m)
 {
struct bridge_iflist *p;
struct mbuf *mc;
struct ifnet *dst_if;
-   int len, used = 0;
-
-   splassert(IPL_NET);
+   int len, s, used = 0;
 
TAILQ_FOREACH(p, sc-sc_iflist, next) {
/*
 * Don't retransmit out of the same interface where
 * the packet was received from.
@@ -1587,11 +1582,13 @@ bridge_broadcast(struct bridge_softc *sc, struct ifnet 
*ifp,
len += ETHER_VLAN_ENCAP_LEN;
 #endif
if ((len - ETHER_HDR_LEN)  dst_if-if_mtu)
bridge_fragment(sc, dst_if, eh, mc);
else {
+   s = splnet();
bridge_ifenqueue(sc, dst_if, mc);
+   splx(s);
}
}
 
if (!used)
m_freem(m);
@@ -1643,11 +1640,11 @@ bridge_span(struct bridge_softc *sc, struct 
ether_header *eh,
 struct mbuf *morig)
 {
struct bridge_iflist *p;
struct ifnet *ifp;
struct mbuf *mc, *m;
-   int error;
+   int s, error;
 
if (TAILQ_EMPTY(sc-sc_spanlist))
return;
 
m = m_copym2(morig, 0, M_COPYALL, M_NOWAIT);
@@ -1679,11 +1676,13 @@ bridge_span(struct bridge_softc *sc, struct 
ether_header *eh,
if (mc == NULL) {
sc-sc_if.if_oerrors++;
continue;
}
 
+   s = splnet();
error = bridge_ifenqueue(sc, ifp, mc);
+   splx(s);
if (error)