]> git.proxmox.com Git - mirror_ovs.git/blob - lib/tc.c
tc: Introduce tc module
[mirror_ovs.git] / lib / tc.c
1 /*
2 * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 Nicira, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <config.h>
18 #include "tc.h"
19 #include <errno.h>
20 #include "netlink-socket.h"
21 #include "netlink.h"
22 #include "openvswitch/ofpbuf.h"
23 #include "openvswitch/vlog.h"
24
25 VLOG_DEFINE_THIS_MODULE(tc);
26
27 /* Returns tc handle 'major':'minor'. */
28 unsigned int
29 tc_make_handle(unsigned int major, unsigned int minor)
30 {
31 return TC_H_MAKE(major << 16, minor);
32 }
33
34 /* Returns the major number from 'handle'. */
35 unsigned int
36 tc_get_major(unsigned int handle)
37 {
38 return TC_H_MAJ(handle) >> 16;
39 }
40
41 /* Returns the minor number from 'handle'. */
42 unsigned int
43 tc_get_minor(unsigned int handle)
44 {
45 return TC_H_MIN(handle);
46 }
47
48 struct tcmsg *
49 tc_make_request(int ifindex, int type, unsigned int flags,
50 struct ofpbuf *request)
51 {
52 struct tcmsg *tcmsg;
53
54 ofpbuf_init(request, 512);
55 nl_msg_put_nlmsghdr(request, sizeof *tcmsg, type, NLM_F_REQUEST | flags);
56 tcmsg = ofpbuf_put_zeros(request, sizeof *tcmsg);
57 tcmsg->tcm_family = AF_UNSPEC;
58 tcmsg->tcm_ifindex = ifindex;
59 /* Caller should fill in tcmsg->tcm_handle. */
60 /* Caller should fill in tcmsg->tcm_parent. */
61
62 return tcmsg;
63 }
64
65 int
66 tc_transact(struct ofpbuf *request, struct ofpbuf **replyp)
67 {
68 int error = nl_transact(NETLINK_ROUTE, request, replyp);
69 ofpbuf_uninit(request);
70 return error;
71 }
72
73 /* Adds or deletes a root ingress qdisc on device with specified ifindex.
74 *
75 * This function is equivalent to running the following when 'add' is true:
76 * /sbin/tc qdisc add dev <devname> handle ffff: ingress
77 *
78 * This function is equivalent to running the following when 'add' is false:
79 * /sbin/tc qdisc del dev <devname> handle ffff: ingress
80 *
81 * Where dev <devname> is the device with specified ifindex name.
82 *
83 * The configuration and stats may be seen with the following command:
84 * /sbin/tc -s qdisc show dev <devname>
85 *
86 * Returns 0 if successful, otherwise a positive errno value.
87 */
88 int
89 tc_add_del_ingress_qdisc(int ifindex, bool add)
90 {
91 struct ofpbuf request;
92 struct tcmsg *tcmsg;
93 int error;
94 int type = add ? RTM_NEWQDISC : RTM_DELQDISC;
95 int flags = add ? NLM_F_EXCL | NLM_F_CREATE : 0;
96
97 tcmsg = tc_make_request(ifindex, type, flags, &request);
98 tcmsg->tcm_handle = tc_make_handle(0xffff, 0);
99 tcmsg->tcm_parent = TC_H_INGRESS;
100 nl_msg_put_string(&request, TCA_KIND, "ingress");
101 nl_msg_put_unspec(&request, TCA_OPTIONS, NULL, 0);
102
103 error = tc_transact(&request, NULL);
104 if (error) {
105 /* If we're deleting the qdisc, don't worry about some of the
106 * error conditions. */
107 if (!add && (error == ENOENT || error == EINVAL)) {
108 return 0;
109 }
110 return error;
111 }
112
113 return 0;
114 }