> On 12 Oct 2015, at 12:00 AM, Alexandr Nedvedicky 
> <alexandr.nedvedi...@oracle.com> wrote:
> 
> Hello,
> 
> patch below introduces struct refcnt to pfi_kif structure. Patch also changes
> pfi_kif_get() function to always return a reference to pfi_kif instance.
> 
> Furthermore existing functions pfi_kif_ref()/pfi_kif_unref() are thrown away
> in favor of pfi_kif_take()/pfi_kif_rele(), which follow naming convention
> set by refcnt_init(9).  Patch also removes kif reference types (enum
> pfi_kif_refs).
> 
> Patch also updates if_pfsync.c file. I'm bit puzzled with test as follows
> in pfsync_in_clr():
> 
> 770         for (i = 0; i < count; i++) {
> 771                 clr = (struct pfsync_clr *)buf + len * i;
> 772                 creatorid = clr->creatorid;
> 773 
> 774                 if (clr->ifname[0] == '\0') {
> ...
> 783                 } else {
> 784                         if (pfi_kif_get(clr->ifname) == NULL)
> 789                                 continue;
> 790 
> 
> I could not make any sense of line 784. Are we just making sure particular kif
> object exists for clr->ifname? Note pfi_kif_get() creates kif for us if it
> does not exist. If we want to query for kif existence only patch offers
> pfi_kif_check() function. I need some advice here if we should keep, what's
> currently in patch or switch to pfi_kif_check().

my name is probably against that code.

i didn't realise that pfi_kif_get creates a kif on demand. however, it also 
uses malloc(, , M_NOWAIT) to try and allocate it, which can fail and cause 
pfi_kif_get to return NULL.

> 
> thanks and
> regards
> sasha
> 
> ---------8<----------------8<----------------8<---------------8<--------
> Index: if_pfsync.c
> ===================================================================
> RCS file: /cvs/src/sys/net/if_pfsync.c,v
> retrieving revision 1.220
> diff -u -p -r1.220 if_pfsync.c
> --- if_pfsync.c       11 Sep 2015 08:17:06 -0000      1.220
> +++ if_pfsync.c       11 Oct 2015 13:46:11 -0000
> @@ -631,6 +631,8 @@ pfsync_state_import(struct pfsync_state 
>       }
>       CLR(st->state_flags, PFSTATE_ACK);
> 
> +     pfi_kif_rele(kif);
> +
>       return (0);
> 
>  cleanup:
> @@ -650,6 +652,9 @@ pfsync_state_import(struct pfsync_state 
>                       pool_put(&pf_state_scrub_pl, st->src.scrub);
>               pool_put(&pf_state_pl, st);
>       }
> +
> +     pfi_kif_rele(kif);
> +
>       return (error);
> }
> 
> @@ -759,6 +764,7 @@ pfsync_in_clr(caddr_t buf, int len, int 
>       struct pf_state *st, *nexts;
>       struct pf_state_key *sk, *nextsk;
>       struct pf_state_item *si;
> +     struct pfi_kif *kif;
>       u_int32_t creatorid;
> 
>       for (i = 0; i < count; i++) {
> @@ -775,7 +781,11 @@ pfsync_in_clr(caddr_t buf, int len, int 
>                               }
>                       }
>               } else {
> -                     if (pfi_kif_get(clr->ifname) == NULL)
> +                     /*
> +                      * Do we realize here the pfi_kif_get() actually
> +                      * creates kif for name if it does not exist? 
> +                      */
> +                     if ((kif = pfi_kif_get(clr->ifname)) == NULL)
>                               continue;
> 
>                       /* XXX correct? */
> @@ -791,6 +801,8 @@ pfsync_in_clr(caddr_t buf, int len, int 
>                                       }
>                               }
>                       }
> +
> +                     pfi_kif_rele(kif);
>               }
>       }
> 
> Index: pf.c
> ===================================================================
> RCS file: /cvs/src/sys/net/pf.c,v
> retrieving revision 1.946
> diff -u -p -r1.946 pf.c
> --- pf.c      8 Oct 2015 11:36:51 -0000       1.946
> +++ pf.c      11 Oct 2015 13:46:14 -0000
> @@ -944,7 +944,7 @@ pf_state_insert(struct pfi_kif *kif, str
>       TAILQ_INSERT_TAIL(&state_list, s, entry_list);
>       pf_status.fcounters[FCNT_STATE_INSERT]++;
>       pf_status.states++;
> -     pfi_kif_ref(kif, PFI_KIF_REF_STATE);
> +     pfi_kif_take(kif);
> #if NPFSYNC > 0
>       pfsync_insert_state(s);
> #endif        /* NPFSYNC > 0 */
> @@ -1315,7 +1315,7 @@ pf_free_state(struct pf_state *cur)
>               pool_put(&pf_rule_item_pl, ri);
>       }
>       pf_normalize_tcp_cleanup(cur);
> -     pfi_kif_unref(cur->kif, PFI_KIF_REF_STATE);
> +     pfi_kif_rele(cur->kif);
>       TAILQ_REMOVE(&state_list, cur, entry_list);
>       if (cur->tag)
>               pf_tag_unref(cur->tag);
> Index: pf_if.c
> ===================================================================
> RCS file: /cvs/src/sys/net/pf_if.c,v
> retrieving revision 1.80
> diff -u -p -r1.80 pf_if.c
> --- pf_if.c   4 Sep 2015 21:40:25 -0000       1.80
> +++ pf_if.c   11 Oct 2015 13:46:14 -0000
> @@ -107,7 +107,7 @@ pfi_kif_get(const char *kif_name)
>       bzero(&s, sizeof(s));
>       strlcpy(s.pfik_name, kif_name, sizeof(s.pfik_name));
>       if ((kif = RB_FIND(pfi_ifhead, &pfi_ifs, (struct pfi_kif *)&s)) != NULL)
> -             return (kif);
> +             return (pfi_kif_take(kif));
> 
>       /* create new one */
>       if ((kif = malloc(sizeof(*kif), PFI_MTYPE, M_NOWAIT|M_ZERO)) == NULL)
> @@ -116,6 +116,7 @@ pfi_kif_get(const char *kif_name)
>       strlcpy(kif->pfik_name, kif_name, sizeof(kif->pfik_name));
>       kif->pfik_tzero = time_second;
>       TAILQ_INIT(&kif->pfik_dynaddrs);
> +     PF_REF_INIT(kif->pfik_refcnt);
> 
>       if (!strcmp(kif->pfik_name, "any")) {
>               /* both so it works in the ioctl and the regular case */
> @@ -124,72 +125,21 @@ pfi_kif_get(const char *kif_name)
>       }
> 
>       RB_INSERT(pfi_ifhead, &pfi_ifs, kif);
> +     /* 
> +      * there is no pfi_kif_remove(), hence caller shares reference with
> +      * pfi_ifs look up table.
> +      */
>       return (kif);
> }
> 
> -void
> -pfi_kif_ref(struct pfi_kif *kif, enum pfi_kif_refs what)
> -{
> -     switch (what) {
> -     case PFI_KIF_REF_RULE:
> -             kif->pfik_rules++;
> -             break;
> -     case PFI_KIF_REF_STATE:
> -             kif->pfik_states++;
> -             break;
> -     case PFI_KIF_REF_ROUTE:
> -             kif->pfik_routes++;
> -             break;
> -     default:
> -             panic("pfi_kif_ref with unknown type");
> -     }
> -}
> -
> -void
> -pfi_kif_unref(struct pfi_kif *kif, enum pfi_kif_refs what)
> +int
> +pfi_kif_check(const char *kif_name)
> {
> -     if (kif == NULL)
> -             return;
> -
> -     switch (what) {
> -     case PFI_KIF_REF_NONE:
> -             break;
> -     case PFI_KIF_REF_RULE:
> -             if (kif->pfik_rules <= 0) {
> -                     DPFPRINTF(LOG_ERR,
> -                         "pfi_kif_unref: rules refcount <= 0");
> -                     return;
> -             }
> -             kif->pfik_rules--;
> -             break;
> -     case PFI_KIF_REF_STATE:
> -             if (kif->pfik_states <= 0) {
> -                     DPFPRINTF(LOG_ERR,
> -                         "pfi_kif_unref: state refcount <= 0");
> -                     return;
> -             }
> -             kif->pfik_states--;
> -             break;
> -     case PFI_KIF_REF_ROUTE:
> -             if (kif->pfik_routes <= 0) {
> -                     DPFPRINTF(LOG_ERR,
> -                         "pfi_kif_unref: state refcount <= 0");
> -                     return;
> -             }
> -             kif->pfik_routes--;
> -             break;
> -     default:
> -             panic("pfi_kif_unref with unknown type");
> -     }
> -
> -     if (kif->pfik_ifp != NULL || kif->pfik_group != NULL || kif == pfi_all)
> -             return;
> -
> -     if (kif->pfik_rules || kif->pfik_states || kif->pfik_routes)
> -             return;
> +     struct pfi_kif_cmp      s;
> 
> -     RB_REMOVE(pfi_ifhead, &pfi_ifs, kif);
> -     free(kif, PFI_MTYPE, 0);
> +     bzero(&s, sizeof(s));
> +     strlcpy(s.pfik_name, kif_name, sizeof (s.pfik_name));
> +     return (RB_FIND(pfi_ifhead, &pfi_ifs, (struct pfi_kif *)&s));
> }
> 
> int
> @@ -258,7 +208,7 @@ pfi_detach_ifnet(struct ifnet *ifp)
> 
>       kif->pfik_ifp = NULL;
>       ifp->if_pf_kif = NULL;
> -     pfi_kif_unref(kif, PFI_KIF_REF_NONE);
> +     pfi_kif_rele(kif);
> 
>       splx(s);
> }
> @@ -275,6 +225,7 @@ pfi_attach_ifgroup(struct ifg_group *ifg
>       if ((kif = pfi_kif_get(ifg->ifg_group)) == NULL)
>               panic("pfi_kif_get failed");
> 
> +     KASSERT(kif->pfik_group == NULL);
>       kif->pfik_group = ifg;
>       ifg->ifg_pf_kif = (caddr_t)kif;
> 
> @@ -295,7 +246,7 @@ pfi_detach_ifgroup(struct ifg_group *ifg
> 
>       kif->pfik_group = NULL;
>       ifg->ifg_pf_kif = NULL;
> -     pfi_kif_unref(kif, PFI_KIF_REF_NONE);
> +     pfi_kif_rele(kif);
>       splx(s);
> }
> 
> @@ -312,6 +263,8 @@ pfi_group_change(const char *group)
> 
>       pfi_kif_update(kif);
> 
> +     pfi_kif_rele(kif);
> +
>       splx(s);
> }
> 
> @@ -371,7 +324,6 @@ pfi_dynaddr_setup(struct pf_addr_wrap *a
>               rv = 1;
>               goto _bad;
>       }
> -     pfi_kif_ref(dyn->pfid_kif, PFI_KIF_REF_RULE);
> 
>       dyn->pfid_net = pfi_unmask(&aw->v.a.mask);
>       if (af == AF_INET && dyn->pfid_net == 32)
> @@ -414,7 +366,7 @@ _bad:
>       if (ruleset != NULL)
>               pf_remove_if_empty_ruleset(ruleset);
>       if (dyn->pfid_kif != NULL)
> -             pfi_kif_unref(dyn->pfid_kif, PFI_KIF_REF_RULE);
> +             pfi_kif_rele(dyn->pfid_kif);
>       pool_put(&pfi_addr_pl, dyn);
>       splx(s);
>       return (rv);
> @@ -595,7 +547,7 @@ pfi_dynaddr_remove(struct pf_addr_wrap *
> 
>       s = splsoftnet();
>       TAILQ_REMOVE(&aw->p.dyn->pfid_kif->pfik_dynaddrs, aw->p.dyn, entry);
> -     pfi_kif_unref(aw->p.dyn->pfid_kif, PFI_KIF_REF_RULE);
> +     pfi_kif_rele(aw->p.dyn->pfid_kif);
>       aw->p.dyn->pfid_kif = NULL;
>       pfr_detach_table(aw->p.dyn->pfid_kt);
>       aw->p.dyn->pfid_kt = NULL;
> @@ -709,14 +661,14 @@ pfi_get_ifaces(const char *name, struct 
>               if (*size > n++) {
>                       if (!p->pfik_tzero)
>                               p->pfik_tzero = time_second;
> -                     pfi_kif_ref(p, PFI_KIF_REF_RULE);
> +                     pfi_kif_take(p);
>                       if (copyout(p, buf++, sizeof(*buf))) {
> -                             pfi_kif_unref(p, PFI_KIF_REF_RULE);
> +                             pfi_kif_rele(p);
>                               splx(s);
>                               return (EFAULT);
>                       }
>                       nextp = RB_NEXT(pfi_ifhead, &pfi_ifs, p);
> -                     pfi_kif_unref(p, PFI_KIF_REF_RULE);
> +                     pfi_kif_rele(p);
>               }
>       }
>       splx(s);
> @@ -810,3 +762,28 @@ pfi_unmask(void *addr)
>       return (b);
> }
> 
> +struct pfi_kif *
> +pfi_kif_take(struct pfi_kif *kif)
> +{
> +     if (kif != pfi_all) {
> +             PF_REF_TAKE(kif->pfik_refcnt);
> +     }
> +
> +     return (kif);
> +}
> +
> +void
> +pfi_kif_rele(struct pfi_kif *kif)
> +{
> +     if (kif == pfi_all)
> +             return;
> +
> +     if (PF_REF_RELE(kif->pfik_refcnt)) {
> +             KASSERT(kif->pfik_ifp == NULL);
> +             KASSERT(kif->pfik_group == NULL);
> +             KASSERT(TAILQ_EMPTY(&kif->pfik_dynaddrs));
> +
> +             RB_REMOVE(pfi_ifhead, &pfi_ifs, kif);
> +             free(kif, PFI_MTYPE, 0);
> +     }
> +}
> Index: pf_ioctl.c
> ===================================================================
> RCS file: /cvs/src/sys/net/pf_ioctl.c,v
> retrieving revision 1.290
> diff -u -p -r1.290 pf_ioctl.c
> --- pf_ioctl.c        4 Sep 2015 21:40:25 -0000       1.290
> +++ pf_ioctl.c        11 Oct 2015 13:46:15 -0000
> @@ -289,11 +289,11 @@ pf_rm_rule(struct pf_rulequeue *rulequeu
>               if (rule->overload_tbl)
>                       pfr_detach_table(rule->overload_tbl);
>       }
> -     pfi_kif_unref(rule->rcv_kif, PFI_KIF_REF_RULE);
> -     pfi_kif_unref(rule->kif, PFI_KIF_REF_RULE);
> -     pfi_kif_unref(rule->rdr.kif, PFI_KIF_REF_RULE);
> -     pfi_kif_unref(rule->nat.kif, PFI_KIF_REF_RULE);
> -     pfi_kif_unref(rule->route.kif, PFI_KIF_REF_RULE);
> +     PFI_KIF_RELE(rule->rcv_kif);
> +     PFI_KIF_RELE(rule->kif);
> +     PFI_KIF_RELE(rule->rdr.kif);
> +     PFI_KIF_RELE(rule->nat.kif);
> +     PFI_KIF_RELE(rule->route.kif);
>       pf_anchor_remove(rule);
>       pool_put(&pf_rule_pl, rule);
> }
> @@ -529,7 +529,7 @@ pf_free_queues(struct pf_queuehead *wher
>               if (ifp && q->kif->pfik_ifp != ifp)
>                       continue;
>               TAILQ_REMOVE(where, q, entries);
> -             pfi_kif_unref(q->kif, PFI_KIF_REF_RULE);
> +             PFI_KIF_RELE(q->kif);
>               pool_put(&pf_queue_pl, q);
>       }
>       return (0);
> @@ -788,8 +788,6 @@ pf_kif_setup(char *ifname, struct pfi_ki
>               *kif = pfi_kif_get(ifname);
>               if (*kif == NULL)
>                       return (EINVAL);
> -
> -             pfi_kif_ref(*kif, PFI_KIF_REF_RULE);
>       } else
>               *kif = NULL;
> 
> @@ -1035,7 +1033,6 @@ pfioctl(dev_t dev, u_long cmd, caddr_t a
>                       break;
>               }
>               /* XXX resolve bw percentage specs */
> -             pfi_kif_ref(qs->kif, PFI_KIF_REF_RULE);
>               if (qs->qlimit == 0)
>                       qs->qlimit = HFSC_DEFAULT_QLIMIT;
>               TAILQ_INSERT_TAIL(pf_queues_inactive, qs, entries);
> Index: pf_table.c
> ===================================================================
> RCS file: /cvs/src/sys/net/pf_table.c,v
> retrieving revision 1.115
> diff -u -p -r1.115 pf_table.c
> --- pf_table.c        7 Oct 2015 11:57:44 -0000       1.115
> +++ pf_table.c        11 Oct 2015 13:46:17 -0000
> @@ -847,8 +847,6 @@ pfr_create_kentry(struct pfr_addr *ad)
>       case PFRKE_ROUTE:
>               if (ad->pfra_ifname[0])
>                       ke->pfrke_rkif = pfi_kif_get(ad->pfra_ifname);
> -             if (ke->pfrke_rkif)
> -                     pfi_kif_ref(ke->pfrke_rkif, PFI_KIF_REF_ROUTE);
>               break;
>       default:
>               panic("unknown pfrke_type %d", ke->pfrke_type);
> @@ -893,8 +891,7 @@ pfr_destroy_kentry(struct pfr_kentry *ke
>       if (ke->pfrke_counters)
>               pool_put(&pfr_kcounters_pl, ke->pfrke_counters);
>       if (ke->pfrke_type == PFRKE_COST || ke->pfrke_type == PFRKE_ROUTE)
> -             pfi_kif_unref(((struct pfr_kentry_all *)ke)->pfrke_rkif,
> -                 PFI_KIF_REF_ROUTE);
> +             pfi_kif_rele(((struct pfr_kentry_all *)ke)->pfrke_rkif);
>       pool_put(&pfr_kentry_pl[ke->pfrke_type], ke);
> }
> 
> Index: pfvar.h
> ===================================================================
> RCS file: /cvs/src/sys/net/pfvar.h,v
> retrieving revision 1.420
> diff -u -p -r1.420 pfvar.h
> --- pfvar.h   19 Aug 2015 21:22:41 -0000      1.420
> +++ pfvar.h   11 Oct 2015 13:46:17 -0000
> @@ -38,6 +38,7 @@
> #include <sys/tree.h>
> #include <sys/rwlock.h>
> #include <sys/syslimits.h>
> +#include <sys/refcnt.h>
> 
> #include <net/radix.h>
> #include <net/route.h>
> @@ -55,6 +56,8 @@ struct ip6_hdr;
> #endif
> #endif
> 
> +typedef struct refcnt        pf_refcnt_t;
> +
> enum  { PF_INOUT, PF_IN, PF_OUT, PF_FWD };
> enum  { PF_PASS, PF_DROP, PF_SCRUB, PF_NOSCRUB, PF_NAT, PF_NONAT,
>         PF_BINAT, PF_NOBINAT, PF_RDR, PF_NORDR, PF_SYNPROXY_DROP, PF_DEFER,
> @@ -1125,17 +1128,8 @@ struct pfi_kif {
>       void                            *pfik_ah_cookie;
>       struct ifnet                    *pfik_ifp;
>       struct ifg_group                *pfik_group;
> -     int                              pfik_states;
> -     int                              pfik_rules;
> -     int                              pfik_routes;
>       TAILQ_HEAD(, pfi_dynaddr)        pfik_dynaddrs;
> -};
> -
> -enum pfi_kif_refs {
> -     PFI_KIF_REF_NONE,
> -     PFI_KIF_REF_STATE,
> -     PFI_KIF_REF_RULE,
> -     PFI_KIF_REF_ROUTE
> +     pf_refcnt_t                      pfik_refcnt;
> };
> 
> #define PFI_IFLAG_SKIP                0x0100  /* skip filtering on interface 
> */
> @@ -1811,8 +1805,9 @@ extern struct pfi_kif           *pfi_all;
> 
> void           pfi_initialize(void);
> struct pfi_kif        *pfi_kif_get(const char *);
> -void          pfi_kif_ref(struct pfi_kif *, enum pfi_kif_refs);
> -void          pfi_kif_unref(struct pfi_kif *, enum pfi_kif_refs);
> +struct pfi_kif       *pfi_kif_take(struct pfi_kif *);
> +void          pfi_kif_rele(struct pfi_kif *);
> +int           pfi_kif_check(const char *);
> int            pfi_kif_match(struct pfi_kif *, struct pfi_kif *);
> void           pfi_attach_ifnet(struct ifnet *);
> void           pfi_detach_ifnet(struct ifnet *);
> @@ -1909,5 +1904,16 @@ void                    pf_cksum(struct pf_pdesc *, 
> stru
> 
> #endif /* _KERNEL */
> 
> +#define      PF_REF_INIT(_x_)        refcnt_init(&(_x_))
> +
> +#define      PF_REF_TAKE(_x_)        refcnt_take(&(_x_))
> +
> +#define      PF_REF_RELE(_x_)        refcnt_rele(&(_x_)) 
> +
> +#define      PFI_KIF_TAKE(_kif_)     \
> +     (((_kif_) != NULL) ? pfi_kif_take((_kif_)) : NULL)
> +
> +#define      PFI_KIF_RELE(_kif_)     \
> +     (((_kif_) != NULL) ? pfi_kif_rele((_kif_)) : ((void)(0)))
> 
> #endif /* _NET_PFVAR_H_ */
> 

it all looks good to me. ok.

dlg

Reply via email to