1+ #ifdef _KERNEL_OPT
2+ #include "opt_altq.h"
3+ #include "opt_inet.h"
4+ #endif
5+
6+ #include <sys/systm.h>
7+ #include <sys/pool.h>
8+ #include <altq/altq.h>
9+ #include "npf.h"
10+
11+ #ifdef ALTQ
12+
13+ TAILQ_HEAD (npf_tags , npf_tagname ) npf_tags = TAILQ_HEAD_INITIALIZER (npf_tags ),
14+ npf_qids = TAILQ_HEAD_INITIALIZER (npf_qids );
15+
16+ void tag_unref (struct npf_tags * , u_int16_t );
17+ uint16_t npftagname2tag (struct npf_tags * , char * );
18+
19+ struct npf_altqqueue * npf_altqs_active ;
20+ struct npf_altqqueue * npf_altqs_inactive ;
21+ struct npf_altqqueue npf_altqs [2 ];
22+
23+ struct pool npf_altq_pl ;
24+ int npf_altq_loaded = 0 ;
25+
26+ /* npf interface to start altq */
27+ void
28+ npf_altq_init (void )
29+ {
30+ pool_init (& npf_altq_pl , sizeof (struct npf_altq ), 0 , 0 , 0 , "npfaltqpl" ,
31+ & pool_allocator_nointr , IPL_NONE );
32+ TAILQ_INIT (& npf_altqs [0 ]);
33+ TAILQ_INIT (& npf_altqs [1 ]);
34+ npf_altqs_active = & npf_altqs [0 ];
35+ npf_altqs_inactive = & npf_altqs [1 ];
36+ }
37+
38+ int
39+ npf_begin_altq (void )
40+ {
41+ struct npf_altq * altq ;
42+ int error = 0 ;
43+ /* Purge the old altq list */
44+ while ((altq = TAILQ_FIRST (npf_altqs_inactive )) != NULL ) {
45+ TAILQ_REMOVE (npf_altqs_inactive , altq , entries );
46+ if (altq -> qname [0 ] == 0 ) {
47+ /* detach and destroy the discipline */
48+ if ((error = altq_remove (altq )) != 0 )
49+ return error ;
50+ } else
51+ npf_qid_unref (altq -> qid );
52+ pool_put (& npf_altq_pl , altq );
53+ }
54+
55+ return 0 ;
56+ }
57+
58+ void
59+ npf_qid_unref (u_int32_t qid )
60+ {
61+ tag_unref (& npf_qids , (u_int16_t )qid );
62+ }
63+
64+ void
65+ tag_unref (struct npf_tags * head , u_int16_t tag )
66+ {
67+ struct npf_tagname * p , * next ;
68+ if (tag == 0 )
69+ return ;
70+ for (p = TAILQ_FIRST (head ); p != NULL ; p = next ) {
71+ next = TAILQ_NEXT (p , entries );
72+ if (tag == p -> tag ) {
73+ if (-- p -> ref == 0 ) {
74+ TAILQ_REMOVE (head , p , entries );
75+ free (p , M_TEMP );
76+ }
77+ break ;
78+ }
79+ }
80+ }
81+
82+ int
83+ npf_add_altq (void * data )
84+ {
85+ struct npfioc_altq * paa = (struct npfioc_altq * )data ;
86+ struct npf_altq * altq , * a ;
87+ int error ;
88+
89+ altq = pool_get (& npf_altq_pl , PR_NOWAIT );
90+ if (altq == NULL ) {
91+ error = ENOMEM ;
92+ return error ;
93+ }
94+ memcpy (altq , & paa -> altq , sizeof (* altq ));
95+ /*
96+ * if this is for a queue, find the discipline and
97+ * copy the necessary fields
98+ */
99+ if (altq -> qname [0 ] != 0 ) {
100+ if ((altq -> qid = npf_qname2qid (altq -> qname )) == 0 ) {
101+ error = EBUSY ;
102+ pool_put (& npf_altq_pl , altq );
103+ return error ;
104+ }
105+ TAILQ_FOREACH (a , npf_altqs_inactive , entries ) {
106+ if (strncmp (a -> ifname , altq -> ifname ,
107+ IFNAMSIZ ) == 0 && a -> qname [0 ] == 0 ) {
108+ altq -> altq_disc = a -> altq_disc ;
109+ break ;
110+ }
111+ }
112+ }
113+ error = altq_add (altq );
114+ if (error ) {
115+ pool_put (& npf_altq_pl , altq );
116+ return error ;
117+ }
118+ TAILQ_INSERT_TAIL (npf_altqs_inactive , altq , entries );
119+ memcpy (& paa -> altq , altq , sizeof (paa -> altq ));
120+
121+ if (!npf_altq_loaded )
122+ npf_altq_loaded = 1 ;
123+ return 0 ;
124+ }
125+
126+ u_int32_t
127+ npf_qname2qid (char * qname )
128+ {
129+ return ((u_int32_t )npftagname2tag (& npf_qids , qname ));
130+ }
131+
132+ u_int16_t
133+ npftagname2tag (struct npf_tags * head , char * tagname )
134+ {
135+ struct npf_tagname * tag , * p = NULL ;
136+ u_int16_t new_tagid = 1 ;
137+ TAILQ_FOREACH (tag , head , entries )
138+ if (strcmp (tagname , tag -> name ) == 0 ) {
139+ tag -> ref ++ ;
140+ return (tag -> tag );
141+ }
142+ /*
143+ * to avoid fragmentation, we do a linear search from the beginning
144+ * and take the first free slot we find. if there is none or the list
145+ * is empty, append a new entry at the end.
146+ */
147+ /* new entry */
148+ if (!TAILQ_EMPTY (head ))
149+ for (p = TAILQ_FIRST (head ); p != NULL &&
150+ p -> tag == new_tagid ; p = TAILQ_NEXT (p , entries ))
151+ new_tagid = p -> tag + 1 ;
152+ if (new_tagid > TAGID_MAX )
153+ return 0 ;
154+ /* allocate and fill new struct npf_tagname */
155+ tag = malloc (sizeof (* tag ),
156+ M_TEMP , M_NOWAIT );
157+ if (tag == NULL )
158+ return 0 ;
159+ memset (tag , 0 , sizeof (* tag ));
160+ strlcpy (tag -> name , tagname , sizeof (tag -> name ));
161+ tag -> tag = new_tagid ;
162+ tag -> ref ++ ;
163+ if (p != NULL ) /* insert new entry before p */
164+ TAILQ_INSERT_BEFORE (p , tag , entries );
165+ else /* either list empty or no free slot in between */
166+ TAILQ_INSERT_TAIL (head , tag , entries );
167+ return (tag -> tag );
168+ }
169+
170+ int
171+ npf_get_altqs (void * data )
172+ {
173+ struct npfioc_altq * paa = (struct npfioc_altq * )data ;
174+ struct npf_altq * altq ;
175+ paa -> nr = 0 ;
176+ TAILQ_FOREACH (altq , npf_altqs_active , entries )
177+ paa -> nr ++ ;
178+ return 0 ;
179+ }
180+
181+ #endif /* ALTQ */
0 commit comments