]>
Commit | Line | Data |
---|---|---|
c1c5c723 PB |
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 | } |