~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/sched/act_skbedit.c

Version: ~ [ linux-5.15-rc1 ] ~ [ linux-5.14.5 ] ~ [ linux-5.13.18 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.66 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.147 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.206 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.246 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.282 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.283 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * Copyright (c) 2008, Intel Corporation.
  3  *
  4  * This program is free software; you can redistribute it and/or modify it
  5  * under the terms and conditions of the GNU General Public License,
  6  * version 2, as published by the Free Software Foundation.
  7  *
  8  * This program is distributed in the hope it will be useful, but WITHOUT
  9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 11  * more details.
 12  *
 13  * You should have received a copy of the GNU General Public License along with
 14  * this program; if not, see <http://www.gnu.org/licenses/>.
 15  *
 16  * Author: Alexander Duyck <alexander.h.duyck@intel.com>
 17  */
 18 
 19 #include <linux/module.h>
 20 #include <linux/init.h>
 21 #include <linux/kernel.h>
 22 #include <linux/skbuff.h>
 23 #include <linux/rtnetlink.h>
 24 #include <net/netlink.h>
 25 #include <net/pkt_sched.h>
 26 
 27 #include <linux/tc_act/tc_skbedit.h>
 28 #include <net/tc_act/tc_skbedit.h>
 29 
 30 #define SKBEDIT_TAB_MASK     15
 31 
 32 static int skbedit_net_id;
 33 
 34 static int tcf_skbedit(struct sk_buff *skb, const struct tc_action *a,
 35                        struct tcf_result *res)
 36 {
 37         struct tcf_skbedit *d = a->priv;
 38 
 39         spin_lock(&d->tcf_lock);
 40         d->tcf_tm.lastuse = jiffies;
 41         bstats_update(&d->tcf_bstats, skb);
 42 
 43         if (d->flags & SKBEDIT_F_PRIORITY)
 44                 skb->priority = d->priority;
 45         if (d->flags & SKBEDIT_F_QUEUE_MAPPING &&
 46             skb->dev->real_num_tx_queues > d->queue_mapping)
 47                 skb_set_queue_mapping(skb, d->queue_mapping);
 48         if (d->flags & SKBEDIT_F_MARK)
 49                 skb->mark = d->mark;
 50 
 51         spin_unlock(&d->tcf_lock);
 52         return d->tcf_action;
 53 }
 54 
 55 static const struct nla_policy skbedit_policy[TCA_SKBEDIT_MAX + 1] = {
 56         [TCA_SKBEDIT_PARMS]             = { .len = sizeof(struct tc_skbedit) },
 57         [TCA_SKBEDIT_PRIORITY]          = { .len = sizeof(u32) },
 58         [TCA_SKBEDIT_QUEUE_MAPPING]     = { .len = sizeof(u16) },
 59         [TCA_SKBEDIT_MARK]              = { .len = sizeof(u32) },
 60 };
 61 
 62 static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
 63                             struct nlattr *est, struct tc_action *a,
 64                             int ovr, int bind)
 65 {
 66         struct tc_action_net *tn = net_generic(net, skbedit_net_id);
 67         struct nlattr *tb[TCA_SKBEDIT_MAX + 1];
 68         struct tc_skbedit *parm;
 69         struct tcf_skbedit *d;
 70         u32 flags = 0, *priority = NULL, *mark = NULL;
 71         u16 *queue_mapping = NULL;
 72         int ret = 0, err, exists = 0;
 73 
 74         if (nla == NULL)
 75                 return -EINVAL;
 76 
 77         err = nla_parse_nested(tb, TCA_SKBEDIT_MAX, nla, skbedit_policy);
 78         if (err < 0)
 79                 return err;
 80 
 81         if (tb[TCA_SKBEDIT_PARMS] == NULL)
 82                 return -EINVAL;
 83 
 84         if (tb[TCA_SKBEDIT_PRIORITY] != NULL) {
 85                 flags |= SKBEDIT_F_PRIORITY;
 86                 priority = nla_data(tb[TCA_SKBEDIT_PRIORITY]);
 87         }
 88 
 89         if (tb[TCA_SKBEDIT_QUEUE_MAPPING] != NULL) {
 90                 flags |= SKBEDIT_F_QUEUE_MAPPING;
 91                 queue_mapping = nla_data(tb[TCA_SKBEDIT_QUEUE_MAPPING]);
 92         }
 93 
 94         if (tb[TCA_SKBEDIT_MARK] != NULL) {
 95                 flags |= SKBEDIT_F_MARK;
 96                 mark = nla_data(tb[TCA_SKBEDIT_MARK]);
 97         }
 98 
 99         parm = nla_data(tb[TCA_SKBEDIT_PARMS]);
100 
101         exists = tcf_hash_check(tn, parm->index, a, bind);
102         if (exists && bind)
103                 return 0;
104 
105         if (!flags) {
106                 tcf_hash_release(a, bind);
107                 return -EINVAL;
108         }
109 
110         if (!exists) {
111                 ret = tcf_hash_create(tn, parm->index, est, a,
112                                       sizeof(*d), bind, false);
113                 if (ret)
114                         return ret;
115 
116                 d = to_skbedit(a);
117                 ret = ACT_P_CREATED;
118         } else {
119                 d = to_skbedit(a);
120                 tcf_hash_release(a, bind);
121                 if (!ovr)
122                         return -EEXIST;
123         }
124 
125         spin_lock_bh(&d->tcf_lock);
126 
127         d->flags = flags;
128         if (flags & SKBEDIT_F_PRIORITY)
129                 d->priority = *priority;
130         if (flags & SKBEDIT_F_QUEUE_MAPPING)
131                 d->queue_mapping = *queue_mapping;
132         if (flags & SKBEDIT_F_MARK)
133                 d->mark = *mark;
134 
135         d->tcf_action = parm->action;
136 
137         spin_unlock_bh(&d->tcf_lock);
138 
139         if (ret == ACT_P_CREATED)
140                 tcf_hash_insert(tn, a);
141         return ret;
142 }
143 
144 static int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a,
145                             int bind, int ref)
146 {
147         unsigned char *b = skb_tail_pointer(skb);
148         struct tcf_skbedit *d = a->priv;
149         struct tc_skbedit opt = {
150                 .index   = d->tcf_index,
151                 .refcnt  = d->tcf_refcnt - ref,
152                 .bindcnt = d->tcf_bindcnt - bind,
153                 .action  = d->tcf_action,
154         };
155         struct tcf_t t;
156 
157         if (nla_put(skb, TCA_SKBEDIT_PARMS, sizeof(opt), &opt))
158                 goto nla_put_failure;
159         if ((d->flags & SKBEDIT_F_PRIORITY) &&
160             nla_put(skb, TCA_SKBEDIT_PRIORITY, sizeof(d->priority),
161                     &d->priority))
162                 goto nla_put_failure;
163         if ((d->flags & SKBEDIT_F_QUEUE_MAPPING) &&
164             nla_put(skb, TCA_SKBEDIT_QUEUE_MAPPING,
165                     sizeof(d->queue_mapping), &d->queue_mapping))
166                 goto nla_put_failure;
167         if ((d->flags & SKBEDIT_F_MARK) &&
168             nla_put(skb, TCA_SKBEDIT_MARK, sizeof(d->mark),
169                     &d->mark))
170                 goto nla_put_failure;
171         t.install = jiffies_to_clock_t(jiffies - d->tcf_tm.install);
172         t.lastuse = jiffies_to_clock_t(jiffies - d->tcf_tm.lastuse);
173         t.expires = jiffies_to_clock_t(d->tcf_tm.expires);
174         if (nla_put(skb, TCA_SKBEDIT_TM, sizeof(t), &t))
175                 goto nla_put_failure;
176         return skb->len;
177 
178 nla_put_failure:
179         nlmsg_trim(skb, b);
180         return -1;
181 }
182 
183 static int tcf_skbedit_walker(struct net *net, struct sk_buff *skb,
184                               struct netlink_callback *cb, int type,
185                               struct tc_action *a)
186 {
187         struct tc_action_net *tn = net_generic(net, skbedit_net_id);
188 
189         return tcf_generic_walker(tn, skb, cb, type, a);
190 }
191 
192 static int tcf_skbedit_search(struct net *net, struct tc_action *a, u32 index)
193 {
194         struct tc_action_net *tn = net_generic(net, skbedit_net_id);
195 
196         return tcf_hash_search(tn, a, index);
197 }
198 
199 static struct tc_action_ops act_skbedit_ops = {
200         .kind           =       "skbedit",
201         .type           =       TCA_ACT_SKBEDIT,
202         .owner          =       THIS_MODULE,
203         .act            =       tcf_skbedit,
204         .dump           =       tcf_skbedit_dump,
205         .init           =       tcf_skbedit_init,
206         .walk           =       tcf_skbedit_walker,
207         .lookup         =       tcf_skbedit_search,
208 };
209 
210 static __net_init int skbedit_init_net(struct net *net)
211 {
212         struct tc_action_net *tn = net_generic(net, skbedit_net_id);
213 
214         return tc_action_net_init(tn, &act_skbedit_ops, SKBEDIT_TAB_MASK);
215 }
216 
217 static void __net_exit skbedit_exit_net(struct net *net)
218 {
219         struct tc_action_net *tn = net_generic(net, skbedit_net_id);
220 
221         tc_action_net_exit(tn);
222 }
223 
224 static struct pernet_operations skbedit_net_ops = {
225         .init = skbedit_init_net,
226         .exit = skbedit_exit_net,
227         .id   = &skbedit_net_id,
228         .size = sizeof(struct tc_action_net),
229 };
230 
231 MODULE_AUTHOR("Alexander Duyck, <alexander.h.duyck@intel.com>");
232 MODULE_DESCRIPTION("SKB Editing");
233 MODULE_LICENSE("GPL");
234 
235 static int __init skbedit_init_module(void)
236 {
237         return tcf_register_action(&act_skbedit_ops, &skbedit_net_ops);
238 }
239 
240 static void __exit skbedit_cleanup_module(void)
241 {
242         tcf_unregister_action(&act_skbedit_ops, &skbedit_net_ops);
243 }
244 
245 module_init(skbedit_init_module);
246 module_exit(skbedit_cleanup_module);
247 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp