From owner-svn-src-projects@FreeBSD.ORG Sun Jun 3 20:07:38 2012 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 852021065672; Sun, 3 Jun 2012 20:07:38 +0000 (UTC) (envelope-from glebius@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 703D48FC12; Sun, 3 Jun 2012 20:07:38 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q53K7caR081954; Sun, 3 Jun 2012 20:07:38 GMT (envelope-from glebius@svn.freebsd.org) Received: (from glebius@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q53K7cok081952; Sun, 3 Jun 2012 20:07:38 GMT (envelope-from glebius@svn.freebsd.org) Message-Id: <201206032007.q53K7cok081952@svn.freebsd.org> From: Gleb Smirnoff Date: Sun, 3 Jun 2012 20:07:38 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r236526 - projects/pf/head/sys/contrib/pf/net X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 03 Jun 2012 20:07:38 -0000 Author: glebius Date: Sun Jun 3 20:07:37 2012 New Revision: 236526 URL: http://svn.freebsd.org/changeset/base/236526 Log: pfsync_sendout() is usually called when softc has accumulated enough data to send a packet, and now is being requested to add data that would overflow a packet. Thus, swi scheduled at the end of pfsync_sendout() is going to service not a single packet, but a couple of them, and the second one is containg only one piece of pfsync data. This leads to coupling of pfsync pps: every odd packet is full-sized and every even is undersized. To fix this, a flag is added to softc - PFSYNCF_PUSH, which indicates, whether we swi handler needs to sqeeze data from the softc prior to sending packets. In all cases when we need to send data immidiately, this flags is raised prioir to swi_sched(). But in case of usual sc_len overflow, it isn't raised. Modified: projects/pf/head/sys/contrib/pf/net/if_pfsync.c Modified: projects/pf/head/sys/contrib/pf/net/if_pfsync.c ============================================================================== --- projects/pf/head/sys/contrib/pf/net/if_pfsync.c Sun Jun 3 19:25:48 2012 (r236525) +++ projects/pf/head/sys/contrib/pf/net/if_pfsync.c Sun Jun 3 20:07:37 2012 (r236526) @@ -203,6 +203,7 @@ struct pfsync_softc { uint32_t sc_flags; #define PFSYNCF_OK 0x00000001 #define PFSYNCF_DEFER 0x00000002 +#define PFSYNCF_PUSH 0x00000004 uint8_t sc_maxupdates; struct ip sc_template; struct callout sc_tmo; @@ -248,6 +249,7 @@ static VNET_DEFINE(int, pfsync_carp_adj) #define V_pfsync_carp_adj VNET(pfsync_carp_adj) static void pfsync_timeout(void *); +static void pfsync_push(struct pfsync_softc *); static void pfsyncintr(void *); static int pfsync_multicast_setup(struct pfsync_softc *, struct ifnet *, void *); @@ -417,6 +419,7 @@ pfsync_alloc_scrub_memory(struct pfsync_ static int pfsync_state_import(struct pfsync_state *sp, u_int8_t flags) { + struct pfsync_softc *sc = V_pfsyncif; struct pf_state *st = NULL; struct pf_state_key *skw = NULL, *sks = NULL; struct pf_rule *r = NULL; @@ -546,7 +549,7 @@ pfsync_state_import(struct pfsync_state st->state_flags &= ~PFSTATE_NOSYNC; if (st->state_flags & PFSTATE_ACK) { pfsync_q_ins(st, PFSYNC_S_IACK); - swi_sched(V_pfsync_swi_cookie, 0); + pfsync_push(sc); } } st->state_flags &= ~PFSTATE_ACK; @@ -826,6 +829,7 @@ pfsync_upd_tcp(struct pf_state *st, stru static int pfsync_in_upd(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count) { + struct pfsync_softc *sc = V_pfsyncif; struct pfsync_state *sa, *sp; struct pf_state_key *sk; struct pf_state *st; @@ -866,9 +870,9 @@ pfsync_in_upd(struct pfsync_pkt *pkt, st } if (st->state_flags & PFSTATE_ACK) { - PFSYNC_LOCK(V_pfsyncif); + PFSYNC_LOCK(sc); pfsync_undefer_state(st, 1); - PFSYNC_UNLOCK(V_pfsyncif); + PFSYNC_UNLOCK(sc); } sk = st->key[PF_SK_WIRE]; /* XXX right one? */ @@ -898,7 +902,9 @@ pfsync_in_upd(struct pfsync_pkt *pkt, st pfsync_update_state(st); PF_STATE_UNLOCK(st); - swi_sched(V_pfsync_swi_cookie, 0); + PFSYNC_LOCK(sc); + pfsync_push(sc); + PFSYNC_UNLOCK(sc); continue; } pfsync_alloc_scrub_memory(&sp->dst, &st->dst); @@ -916,6 +922,7 @@ pfsync_in_upd(struct pfsync_pkt *pkt, st static int pfsync_in_upd_c(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count) { + struct pfsync_softc *sc = V_pfsyncif; struct pfsync_upd_c *ua, *up; struct pf_state_key *sk; struct pf_state *st; @@ -952,16 +959,16 @@ pfsync_in_upd_c(struct pfsync_pkt *pkt, st = pf_find_state_byid(up->id, up->creatorid); if (st == NULL) { /* We don't have this state. Ask for it. */ - PFSYNC_LOCK(V_pfsyncif); + PFSYNC_LOCK(sc); pfsync_request_update(up->creatorid, up->id); - PFSYNC_UNLOCK(V_pfsyncif); + PFSYNC_UNLOCK(sc); continue; } if (st->state_flags & PFSTATE_ACK) { - PFSYNC_LOCK(V_pfsyncif); + PFSYNC_LOCK(sc); pfsync_undefer_state(st, 1); - PFSYNC_UNLOCK(V_pfsyncif); + PFSYNC_UNLOCK(sc); } sk = st->key[PF_SK_WIRE]; /* XXX right one? */ @@ -990,7 +997,9 @@ pfsync_in_upd_c(struct pfsync_pkt *pkt, pfsync_update_state(st); PF_STATE_UNLOCK(st); - swi_sched(V_pfsync_swi_cookie, 0); + PFSYNC_LOCK(sc); + pfsync_push(sc); + PFSYNC_UNLOCK(sc); continue; } pfsync_alloc_scrub_memory(&up->dst, &st->dst); @@ -1712,7 +1721,7 @@ pfsync_defer(struct pf_state *st, struct callout_init_mtx(&pd->pd_tmo, &sc->sc_mtx, CALLOUT_RETURNUNLOCKED); callout_reset(&pd->pd_tmo, 10, pfsync_defer_tmo, pd); - swi_sched(V_pfsync_swi_cookie, 0); + pfsync_push(sc); return (1); } @@ -1736,7 +1745,7 @@ pfsync_undefer(struct pfsync_deferral *p m_freem(m); else { _IF_ENQUEUE(&sc->sc_ifp->if_snd, m); - swi_sched(V_pfsync_swi_cookie, 0); + pfsync_push(sc); } } @@ -1829,10 +1838,11 @@ pfsync_update_state(struct pf_state *st) default: panic("%s: unexpected sync state %d", __func__, st->sync_state); } - PFSYNC_UNLOCK(sc); if (sync || (time_uptime - st->pfsync_time) < 2) - swi_sched(V_pfsync_swi_cookie, 0); + pfsync_push(sc); + + PFSYNC_UNLOCK(sc); } static void @@ -1868,7 +1878,7 @@ pfsync_request_update(u_int32_t creatori TAILQ_INSERT_TAIL(&sc->sc_upd_req_list, item, ur_entry); sc->sc_len += nlen; - swi_sched(V_pfsync_swi_cookie, 0); + pfsync_push(sc); } static void @@ -1892,7 +1902,7 @@ pfsync_update_state_req(struct pf_state pfsync_q_del(st); case PFSYNC_S_NONE: pfsync_q_ins(st, PFSYNC_S_UPD); - swi_sched(V_pfsync_swi_cookie, 0); + pfsync_push(sc); break; case PFSYNC_S_INS: @@ -2178,16 +2188,23 @@ pfsync_send_plus(void *plus, size_t plus static void pfsync_timeout(void *arg) { -#ifdef VIMAGE struct pfsync_softc *sc = arg; -#endif CURVNET_SET(sc->sc_ifp->if_vnet); - swi_sched(V_pfsync_swi_cookie, 0); + pfsync_push(sc); CURVNET_RESTORE(); } -/* this is a softnet/netisr handler */ +static void +pfsync_push(struct pfsync_softc *sc) +{ + + PFSYNC_LOCK_ASSERT(sc); + + sc->sc_flags |= PFSYNCF_PUSH; + swi_sched(V_pfsync_swi_cookie, 0); +} + static void pfsyncintr(void *arg) { @@ -2197,8 +2214,10 @@ pfsyncintr(void *arg) CURVNET_SET(sc->sc_ifp->if_vnet); PFSYNC_LOCK(sc); - if (sc->sc_len > PFSYNC_MINPKT) + if ((sc->sc_flags & PFSYNCF_PUSH) && sc->sc_len > PFSYNC_MINPKT) { pfsync_sendout(0); + sc->sc_flags &= ~PFSYNCF_PUSH; + } _IF_DEQUEUE_ALL(&sc->sc_ifp->if_snd, m); PFSYNC_UNLOCK(sc);