@@ -278,6 +278,8 @@ int tcf_block_get_ext(struct tcf_block **p_block,
278278 if (!block )
279279 return - ENOMEM ;
280280 INIT_LIST_HEAD (& block -> chain_list );
281+ INIT_LIST_HEAD (& block -> cb_list );
282+
281283 /* Create chain 0 by default, it has to be always present. */
282284 chain = tcf_chain_create (block , 0 );
283285 if (!chain ) {
@@ -354,6 +356,109 @@ void tcf_block_put(struct tcf_block *block)
354356}
355357EXPORT_SYMBOL (tcf_block_put );
356358
359+ struct tcf_block_cb {
360+ struct list_head list ;
361+ tc_setup_cb_t * cb ;
362+ void * cb_ident ;
363+ void * cb_priv ;
364+ unsigned int refcnt ;
365+ };
366+
367+ void * tcf_block_cb_priv (struct tcf_block_cb * block_cb )
368+ {
369+ return block_cb -> cb_priv ;
370+ }
371+ EXPORT_SYMBOL (tcf_block_cb_priv );
372+
373+ struct tcf_block_cb * tcf_block_cb_lookup (struct tcf_block * block ,
374+ tc_setup_cb_t * cb , void * cb_ident )
375+ { struct tcf_block_cb * block_cb ;
376+
377+ list_for_each_entry (block_cb , & block -> cb_list , list )
378+ if (block_cb -> cb == cb && block_cb -> cb_ident == cb_ident )
379+ return block_cb ;
380+ return NULL ;
381+ }
382+ EXPORT_SYMBOL (tcf_block_cb_lookup );
383+
384+ void tcf_block_cb_incref (struct tcf_block_cb * block_cb )
385+ {
386+ block_cb -> refcnt ++ ;
387+ }
388+ EXPORT_SYMBOL (tcf_block_cb_incref );
389+
390+ unsigned int tcf_block_cb_decref (struct tcf_block_cb * block_cb )
391+ {
392+ return -- block_cb -> refcnt ;
393+ }
394+ EXPORT_SYMBOL (tcf_block_cb_decref );
395+
396+ struct tcf_block_cb * __tcf_block_cb_register (struct tcf_block * block ,
397+ tc_setup_cb_t * cb , void * cb_ident ,
398+ void * cb_priv )
399+ {
400+ struct tcf_block_cb * block_cb ;
401+
402+ block_cb = kzalloc (sizeof (* block_cb ), GFP_KERNEL );
403+ if (!block_cb )
404+ return NULL ;
405+ block_cb -> cb = cb ;
406+ block_cb -> cb_ident = cb_ident ;
407+ block_cb -> cb_priv = cb_priv ;
408+ list_add (& block_cb -> list , & block -> cb_list );
409+ return block_cb ;
410+ }
411+ EXPORT_SYMBOL (__tcf_block_cb_register );
412+
413+ int tcf_block_cb_register (struct tcf_block * block ,
414+ tc_setup_cb_t * cb , void * cb_ident ,
415+ void * cb_priv )
416+ {
417+ struct tcf_block_cb * block_cb ;
418+
419+ block_cb = __tcf_block_cb_register (block , cb , cb_ident , cb_priv );
420+ return block_cb ? 0 : - ENOMEM ;
421+ }
422+ EXPORT_SYMBOL (tcf_block_cb_register );
423+
424+ void __tcf_block_cb_unregister (struct tcf_block_cb * block_cb )
425+ {
426+ list_del (& block_cb -> list );
427+ kfree (block_cb );
428+ }
429+ EXPORT_SYMBOL (__tcf_block_cb_unregister );
430+
431+ void tcf_block_cb_unregister (struct tcf_block * block ,
432+ tc_setup_cb_t * cb , void * cb_ident )
433+ {
434+ struct tcf_block_cb * block_cb ;
435+
436+ block_cb = tcf_block_cb_lookup (block , cb , cb_ident );
437+ if (!block_cb )
438+ return ;
439+ __tcf_block_cb_unregister (block_cb );
440+ }
441+ EXPORT_SYMBOL (tcf_block_cb_unregister );
442+
443+ static int tcf_block_cb_call (struct tcf_block * block , enum tc_setup_type type ,
444+ void * type_data , bool err_stop )
445+ {
446+ struct tcf_block_cb * block_cb ;
447+ int ok_count = 0 ;
448+ int err ;
449+
450+ list_for_each_entry (block_cb , & block -> cb_list , list ) {
451+ err = block_cb -> cb (type , type_data , block_cb -> cb_priv );
452+ if (err ) {
453+ if (err_stop )
454+ return err ;
455+ } else {
456+ ok_count ++ ;
457+ }
458+ }
459+ return ok_count ;
460+ }
461+
357462/* Main classifier routine: scans classifier chain attached
358463 * to this qdisc, (optionally) tests for protocol and asks
359464 * specific classifiers.
0 commit comments