diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index beedd0d2b50973d7394a7c929530701b98e374e3..dc24b7f63ef469b8e5f61114b47392539bc41f79 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -1397,6 +1397,19 @@ void tcf_block_put(struct tcf_block *block) EXPORT_SYMBOL(tcf_block_put); +static void (*tmplt_reoffload)(struct tcf_chain *chain, bool add, + flow_setup_cb_t *cb, void *cb_priv); + +static void cls_tmplt_reoffload(struct tcf_chain *chain, bool add, + flow_setup_cb_t *cb, void *cb_priv) +{ + tmplt_reoffload = (void *)kallsyms_lookup_name("fl_tmplt_reoffload"); + if (!tmplt_reoffload) + return; + + tmplt_reoffload(chain, add, cb, cb_priv); +} + static int tcf_block_playback_offloads(struct tcf_block *block, flow_setup_cb_t *cb, void *cb_priv, bool add, bool offload_in_use, @@ -1413,6 +1426,10 @@ tcf_block_playback_offloads(struct tcf_block *block, flow_setup_cb_t *cb, chain_prev = chain, chain = __tcf_get_next_chain(block, chain), tcf_chain_put(chain_prev)) { + if (chain->tmplt_ops && add) + if (!strcmp(chain->tmplt_ops->kind, "flower")) + cls_tmplt_reoffload(chain, true, cb, cb_priv); + for (tp = __tcf_get_next_proto(chain, NULL); tp; tp_prev = tp, tp = __tcf_get_next_proto(chain, tp), @@ -1428,6 +1445,9 @@ tcf_block_playback_offloads(struct tcf_block *block, flow_setup_cb_t *cb, goto err_playback_remove; } } + if (chain->tmplt_ops && !add) + if (!strcmp(chain->tmplt_ops->kind, "flower")) + cls_tmplt_reoffload(chain, false, cb, cb_priv); } return 0; diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c index dc21e7fb1038b93fcc07ec95dfecb7cf3c486e06..5b5c8a7fd39d4c615c587b7e45b9ed17c89c6e41 100644 --- a/net/sched/cls_flower.c +++ b/net/sched/cls_flower.c @@ -2406,6 +2406,29 @@ static void fl_tmplt_destroy(void *tmplt_priv) kfree(tmplt); } +void fl_tmplt_reoffload(struct tcf_chain *chain, bool add, + flow_setup_cb_t *cb, void *cb_priv) +{ + struct fl_flow_tmplt *tmplt = chain->tmplt_priv; + struct flow_cls_offload cls_flower = {}; + + cls_flower.rule = flow_rule_alloc(0); + if (!cls_flower.rule) + return; + + cls_flower.common.chain_index = chain->index; + cls_flower.command = add ? FLOW_CLS_TMPLT_CREATE : + FLOW_CLS_TMPLT_DESTROY; + cls_flower.cookie = (unsigned long) tmplt; + cls_flower.rule->match.dissector = &tmplt->dissector; + cls_flower.rule->match.mask = &tmplt->mask; + cls_flower.rule->match.key = &tmplt->dummy_key; + + cb(TC_SETUP_CLSFLOWER, &cls_flower, cb_priv); + kfree(cls_flower.rule); +} +EXPORT_SYMBOL(fl_tmplt_reoffload); + static int fl_dump_key_val(struct sk_buff *skb, void *val, int val_type, void *mask, int mask_type, int len)