]>
git.proxmox.com Git - ceph.git/blob - ceph/src/spdk/dpdk/drivers/net/tap/tap_tcmsgs.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright 2017 6WIND S.A.
3 * Copyright 2017 Mellanox Technologies, Ltd
7 #include <linux/netlink.h>
12 #include <tap_tcmsgs.h>
26 struct qdisc_custom_arg
{
33 * Initialize a netlink message with a TC header.
36 * The netlink message to fill.
38 * The netdevice ifindex where the rule will be applied.
40 * The type of TC message to create (RTM_NEWTFILTER, RTM_NEWQDISC, etc.).
42 * Overrides the default netlink flags for this msg with those specified.
45 tc_init_msg(struct nlmsg
*msg
, uint16_t ifindex
, uint16_t type
, uint16_t flags
)
47 struct nlmsghdr
*n
= &msg
->nh
;
49 n
->nlmsg_len
= NLMSG_LENGTH(sizeof(struct tcmsg
));
52 n
->nlmsg_flags
= flags
;
54 n
->nlmsg_flags
= NLM_F_REQUEST
| NLM_F_ACK
;
55 msg
->t
.tcm_family
= AF_UNSPEC
;
56 msg
->t
.tcm_ifindex
= ifindex
;
60 * Delete a specific QDISC identified by its iface, and it's handle and parent.
63 * The netlink socket file descriptor used for communication.
65 * The netdevice ifindex on whom the deletion will happen.
67 * Additional info to identify the QDISC (handle and parent).
70 * 0 on success, -1 otherwise with errno set.
73 qdisc_del(int nlsk_fd
, uint16_t ifindex
, struct qdisc
*qinfo
)
78 tc_init_msg(&msg
, ifindex
, RTM_DELQDISC
, 0);
79 msg
.t
.tcm_handle
= qinfo
->handle
;
80 msg
.t
.tcm_parent
= qinfo
->parent
;
81 /* if no netlink socket is provided, create one */
86 "Could not delete QDISC: null netlink socket");
92 if (tap_nl_send(fd
, &msg
.nh
) < 0)
94 if (tap_nl_recv_ack(fd
) < 0)
97 return tap_nl_final(fd
);
106 * Add the multiqueue QDISC with MULTIQ_MAJOR_HANDLE handle.
109 * The netlink socket file descriptor used for communication.
111 * The netdevice ifindex where to add the multiqueue QDISC.
114 * 0 on success, -1 otherwise with errno set.
117 qdisc_add_multiq(int nlsk_fd
, uint16_t ifindex
)
119 struct tc_multiq_qopt opt
= {0};
122 tc_init_msg(&msg
, ifindex
, RTM_NEWQDISC
,
123 NLM_F_REQUEST
| NLM_F_ACK
| NLM_F_EXCL
| NLM_F_CREATE
);
124 msg
.t
.tcm_handle
= TC_H_MAKE(MULTIQ_MAJOR_HANDLE
, 0);
125 msg
.t
.tcm_parent
= TC_H_ROOT
;
126 tap_nlattr_add(&msg
.nh
, TCA_KIND
, sizeof("multiq"), "multiq");
127 tap_nlattr_add(&msg
.nh
, TCA_OPTIONS
, sizeof(opt
), &opt
);
128 if (tap_nl_send(nlsk_fd
, &msg
.nh
) < 0)
130 if (tap_nl_recv_ack(nlsk_fd
) < 0)
136 * Add the ingress QDISC with default ffff: handle.
139 * The netlink socket file descriptor used for communication.
141 * The netdevice ifindex where the QDISC will be added.
144 * 0 on success, -1 otherwise with errno set.
147 qdisc_add_ingress(int nlsk_fd
, uint16_t ifindex
)
151 tc_init_msg(&msg
, ifindex
, RTM_NEWQDISC
,
152 NLM_F_REQUEST
| NLM_F_ACK
| NLM_F_EXCL
| NLM_F_CREATE
);
153 msg
.t
.tcm_handle
= TC_H_MAKE(TC_H_INGRESS
, 0);
154 msg
.t
.tcm_parent
= TC_H_INGRESS
;
155 tap_nlattr_add(&msg
.nh
, TCA_KIND
, sizeof("ingress"), "ingress");
156 if (tap_nl_send(nlsk_fd
, &msg
.nh
) < 0)
158 if (tap_nl_recv_ack(nlsk_fd
) < 0)
164 * Callback function to delete a QDISC.
167 * The netlink message to parse, received from the kernel.
169 * Custom arguments for the callback.
172 * 0 on success, -1 otherwise with errno set.
175 qdisc_del_cb(struct nlmsghdr
*nh
, void *arg
)
177 struct tcmsg
*t
= NLMSG_DATA(nh
);
178 struct list_args
*args
= arg
;
180 struct qdisc qinfo
= {
181 .handle
= t
->tcm_handle
,
182 .parent
= t
->tcm_parent
,
185 /* filter out other ifaces' qdiscs */
186 if (args
->ifindex
!= (unsigned int)t
->tcm_ifindex
)
189 * Use another nlsk_fd (0) to avoid tampering with the current list
192 return qdisc_del(0, args
->ifindex
, &qinfo
);
196 * Iterate over all QDISC, and call the callback() function for each.
199 * The netlink socket file descriptor used for communication.
201 * The netdevice ifindex where to find QDISCs.
202 * @param[in] callback
203 * The function to call for each QDISC.
204 * @param[in, out] arg
205 * The arguments to provide the callback function with.
208 * 0 on success, -1 otherwise with errno set.
211 qdisc_iterate(int nlsk_fd
, uint16_t ifindex
,
212 int (*callback
)(struct nlmsghdr
*, void *), void *arg
)
215 struct list_args args
= {
221 tc_init_msg(&msg
, ifindex
, RTM_GETQDISC
, NLM_F_REQUEST
| NLM_F_DUMP
);
222 if (tap_nl_send(nlsk_fd
, &msg
.nh
) < 0)
224 if (tap_nl_recv(nlsk_fd
, callback
, &args
) < 0)
230 * Delete all QDISCs for a given netdevice.
233 * The netlink socket file descriptor used for communication.
235 * The netdevice ifindex where to find QDISCs.
238 * 0 on success, -1 otherwise with errno set.
241 qdisc_flush(int nlsk_fd
, uint16_t ifindex
)
243 return qdisc_iterate(nlsk_fd
, ifindex
, qdisc_del_cb
, NULL
);
247 * Create the multiqueue QDISC, only if it does not exist already.
250 * The netlink socket file descriptor used for communication.
252 * The netdevice ifindex where to add the multiqueue QDISC.
255 * 0 if the qdisc exists or if has been successfully added.
256 * Return -1 otherwise.
259 qdisc_create_multiq(int nlsk_fd
, uint16_t ifindex
)
263 err
= qdisc_add_multiq(nlsk_fd
, ifindex
);
264 if (err
< 0 && errno
!= -EEXIST
) {
265 TAP_LOG(ERR
, "Could not add multiq qdisc (%d): %s",
266 errno
, strerror(errno
));
273 * Create the ingress QDISC, only if it does not exist already.
276 * The netlink socket file descriptor used for communication.
278 * The netdevice ifindex where to add the ingress QDISC.
281 * 0 if the qdisc exists or if has been successfully added.
282 * Return -1 otherwise.
285 qdisc_create_ingress(int nlsk_fd
, uint16_t ifindex
)
289 err
= qdisc_add_ingress(nlsk_fd
, ifindex
);
290 if (err
< 0 && errno
!= -EEXIST
) {
291 TAP_LOG(ERR
, "Could not add ingress qdisc (%d): %s",
292 errno
, strerror(errno
));