Hello,

On Wed, Aug 10, 2022 at 02:38:16PM +0000, Stefan Butz wrote:
> Hi everyone,
> 
> this mail includes a patch to store pf rules in a red-black tree.
> Currently they are stored in a linked list.
> My system configured with 16000 rules takes about 10 minutes
> to print them out using `pfctl -sr`.
> This patch decreases the time to 4 seconds.
> I was not able to measure a time increase for rule insertion.
> Inserting a lot of labels is still very slow.
> This has to be attacked separatly.

    took me while to figure out why it can take sooo loooong
    to retrieve 16k rules from kernel. this is the answer

1480         case DIOCGETRULE: {
1496                 if (pr->ticket != ruleset->rules.active.ticket) {
1497                         error = EBUSY;
1498                         PF_UNLOCK();
1499                         NET_UNLOCK();
1500                         goto fail;
1501                 }
1502                 rule = TAILQ_FIRST(ruleset->rules.active.ptr);
1503                 while ((rule != NULL) && (rule->nr != pr->nr))
1504                         rule = TAILQ_NEXT(rule, entries);
1505                 if (rule == NULL) {

    so yes, in order to retrieve the next rule in list we must
    always start with the first (HEAD) rule and iterate to rule n+1.

    so I understand a motivation why to solve it using  rb-tree.

    I also (as todd) have some doubts about code in DIOCHANGERULE.
    the current code is able to insert to desired location.
    I don't understand how your new code does that:


1675 
1676                 if (pcr->action == PF_CHANGE_ADD_HEAD)
1677                         oldrule = RB_MIN(pf_ruletree,
1678                             ruleset->rules.active.ptr);
1679                 else if (pcr->action == PF_CHANGE_ADD_TAIL)
1680                         oldrule = RB_MAX(pf_ruletree,
1681                             ruleset->rules.active.ptr);                    
                               
1682                 else {
1683                         oldrule = RB_MIN(pf_ruletree,
1684                             ruleset->rules.active.ptr);
1685                         while ((oldrule != NULL) && (oldrule->nr != 
pcr->nr))
1686                                 oldrule = RB_NEXT(pf_ruletree,
1687                                     ruleset->rules.active.ptr, oldrule);   
                               
1688                         if (oldrule == NULL) {
1689                                 if (newrule != NULL)
1690                                         pf_rm_rule(NULL, newrule);         
                               
1691                                 error = EINVAL;                            
                               
1692                                 PF_UNLOCK();
1693                                 NET_UNLOCK();
1694                                 goto fail;                                 
                               
1695                         }                                                  
                               
1696                 } 
1697 
1698                 if (pcr->action == PF_CHANGE_REMOVE) {
1699                         pf_rm_rule(ruleset->rules.active.ptr, oldrule);    
                               
1700                         ruleset->rules.active.rcount--;
1701                 } else {
1702                         RB_INSERT(pf_ruletree,
1703                             ruleset->rules.active.ptr, newrule);
1704                         ruleset->rules.active.rcount++;
1705                         newrule->ruleset = ruleset;
1706                 }
1707 

    how does RB_INSERT() at line 1702 insert rule to
    desired location. Consider the current rules look like:

        [ 1, 2, 3, 4 ]

    i'm going to insert rule x, which should follow existing rule nr 3

        [ 1, 2, 3, x, 4]

    current code just re-indexes/renumbers the rules after insertion

        [ 1, 2, 3, 4, 5 ], where x gets assigned 4.

    I don't see how does that happen with RB_INSERT().

I think what we really need to fix is the iteration to n-th retrieved
rule we currently have in DIOCGETRULE. I'm working on slightly large
change which updates pf(4) transactions. I'll try to cherry pick
some changes from my in-progress tree and factor out a smaller diff 
which will solve that DIOCGETRULE itch for you. please stay tuned.

thanks and
regards
sashan

Reply via email to