Coverage Report

Created: 2025-07-11 06:12

/src/openvswitch/lib/tc.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 Nicira, Inc.
3
 * Copyright (c) 2016 Mellanox Technologies, Ltd.
4
 *
5
 * Licensed under the Apache License, Version 2.0 (the "License");
6
 * you may not use this file except in compliance with the License.
7
 * You may obtain a copy of the License at:
8
 *
9
 *     http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 */
17
18
#ifndef TC_H
19
#define TC_H 1
20
21
#include <sys/types.h>
22
#include <netinet/in.h> /* Must happen before linux/pkt_cls.h - Glibc #20215 */
23
#include <linux/pkt_cls.h>
24
#include <linux/pkt_sched.h>
25
26
#include "netlink.h"
27
#include "netlink-socket.h"
28
#include "odp-netlink.h"
29
#include "openvswitch/ofpbuf.h"
30
#include "openvswitch/flow.h"
31
#include "openvswitch/tun-metadata.h"
32
33
/* For backwards compatability with older kernels */
34
#ifndef TC_H_CLSACT
35
#define TC_H_CLSACT    TC_H_INGRESS
36
#endif
37
#ifndef TC_H_MIN_INGRESS
38
#define TC_H_MIN_INGRESS       0xFFF2U
39
#endif
40
#ifndef TC_H_MIN_EGRESS
41
#define TC_H_MIN_EGRESS       0xFFF3U
42
#endif
43
44
0
#define TC_INGRESS_PARENT TC_H_MAKE(TC_H_CLSACT, TC_H_MIN_INGRESS)
45
0
#define TC_EGRESS_PARENT TC_H_MAKE(TC_H_CLSACT, TC_H_MIN_EGRESS)
46
47
0
#define TC_POLICY_DEFAULT "none"
48
49
enum tc_flower_reserved_prio {
50
    TC_RESERVED_PRIORITY_NONE,
51
    TC_RESERVED_PRIORITY_POLICE,
52
    TC_RESERVED_PRIORITY_IPV4,
53
    TC_RESERVED_PRIORITY_IPV6,
54
    TC_RESERVED_PRIORITY_VLAN,
55
    __TC_RESERVED_PRIORITY_MAX,
56
57
    TC_MAX_PRIORITY = UINT16_MAX - 1,
58
    /* This priority is reserved solely for probing purposes.
59
     * Since it's not used in actual traffic flows, we assign it a high value
60
     * to avoid impacting vendor specific hardware offload implementations. */
61
    TC_RESERVED_PRIORITY_FEATURE_PROBE
62
};
63
0
#define TC_RESERVED_PRIORITY_MAX (__TC_RESERVED_PRIORITY_MAX - 1)
64
65
66
enum tc_qdisc_hook {
67
    TC_INGRESS,
68
    TC_EGRESS,
69
};
70
71
0
#define METER_POLICE_IDS_BASE 0x10000000
72
0
#define METER_POLICE_IDS_MAX  0x1FFFFFFF
73
74
static inline bool
75
0
tc_is_meter_index(uint32_t index) {
76
0
    if (index >= METER_POLICE_IDS_BASE && index <= METER_POLICE_IDS_MAX) {
77
0
        return true;
78
0
    }
79
0
    return false;
80
0
}
Unexecuted instantiation: netdev.c:tc_is_meter_index
Unexecuted instantiation: netdev-linux.c:tc_is_meter_index
Unexecuted instantiation: netdev-offload-tc.c:tc_is_meter_index
Unexecuted instantiation: tc.c:tc_is_meter_index
Unexecuted instantiation: netdev-offload.c:tc_is_meter_index
81
82
/* Returns tc handle 'major':'minor'. */
83
static inline unsigned int
84
tc_make_handle(unsigned int major, unsigned int minor)
85
0
{
86
0
    return TC_H_MAKE(major << 16, minor);
87
0
}
Unexecuted instantiation: netdev.c:tc_make_handle
Unexecuted instantiation: netdev-linux.c:tc_make_handle
Unexecuted instantiation: netdev-offload-tc.c:tc_make_handle
Unexecuted instantiation: tc.c:tc_make_handle
Unexecuted instantiation: netdev-offload.c:tc_make_handle
88
89
/* Returns the major number from 'handle'. */
90
static inline unsigned int
91
tc_get_major(unsigned int handle)
92
0
{
93
0
    return TC_H_MAJ(handle) >> 16;
94
0
}
Unexecuted instantiation: netdev.c:tc_get_major
Unexecuted instantiation: netdev-linux.c:tc_get_major
Unexecuted instantiation: netdev-offload-tc.c:tc_get_major
Unexecuted instantiation: tc.c:tc_get_major
Unexecuted instantiation: netdev-offload.c:tc_get_major
95
96
/* Returns the minor number from 'handle'. */
97
static inline unsigned int
98
tc_get_minor(unsigned int handle)
99
0
{
100
0
    return TC_H_MIN(handle);
101
0
}
Unexecuted instantiation: netdev.c:tc_get_minor
Unexecuted instantiation: netdev-linux.c:tc_get_minor
Unexecuted instantiation: netdev-offload-tc.c:tc_get_minor
Unexecuted instantiation: tc.c:tc_get_minor
Unexecuted instantiation: netdev-offload.c:tc_get_minor
102
103
struct tcmsg *tc_make_request(int ifindex, int type,
104
                              unsigned int flags, struct ofpbuf *);
105
struct tcamsg *tc_make_action_request(int type, unsigned int flags,
106
                                      struct ofpbuf *request);
107
int tc_transact(struct ofpbuf *request, struct ofpbuf **replyp);
108
int tc_add_del_qdisc(int ifindex, bool add, uint32_t block_id,
109
                     enum tc_qdisc_hook hook);
110
111
struct tc_cookie {
112
    const void *data;
113
    size_t len;
114
};
115
116
struct tc_tunnel_gbp {
117
    ovs_be16 id;
118
    uint8_t flags;
119
    bool id_present;
120
};
121
122
struct tc_flower_tunnel {
123
    struct {
124
        ovs_be32 ipv4_src;
125
        ovs_be32 ipv4_dst;
126
    } ipv4;
127
    struct {
128
        struct in6_addr ipv6_src;
129
        struct in6_addr ipv6_dst;
130
    } ipv6;
131
    uint8_t tos;
132
    uint8_t ttl;
133
    ovs_be16 tp_src;
134
    ovs_be16 tp_dst;
135
    uint32_t tc_enc_flags;
136
    struct tc_tunnel_gbp gbp;
137
    ovs_be64 id;
138
    struct tun_metadata metadata;
139
};
140
141
struct tc_flower_key {
142
    ovs_be16 eth_type;
143
    uint8_t ip_proto;
144
145
    struct eth_addr dst_mac;
146
    struct eth_addr src_mac;
147
148
    ovs_be32 mpls_lse;
149
    ovs_be16 tcp_src;
150
    ovs_be16 tcp_dst;
151
    ovs_be16 tcp_flags;
152
153
    ovs_be16 udp_src;
154
    ovs_be16 udp_dst;
155
156
    ovs_be16 sctp_src;
157
    ovs_be16 sctp_dst;
158
159
    uint8_t icmp_code;
160
    uint8_t icmp_type;
161
162
    uint16_t vlan_id[FLOW_MAX_VLAN_HEADERS];
163
    uint8_t vlan_prio[FLOW_MAX_VLAN_HEADERS];
164
165
    ovs_be16 encap_eth_type[FLOW_MAX_VLAN_HEADERS];
166
167
    uint8_t flags;
168
    uint8_t ip_ttl;
169
    uint8_t ip_tos;
170
171
    uint16_t ct_state;
172
    uint16_t ct_zone;
173
    uint32_t ct_mark;
174
    ovs_u128 ct_label;
175
176
    struct {
177
        ovs_be32 spa;
178
        ovs_be32 tpa;
179
        struct eth_addr sha;
180
        struct eth_addr tha;
181
        uint8_t opcode;
182
    } arp;
183
184
    struct {
185
        ovs_be32 ipv4_src;
186
        ovs_be32 ipv4_dst;
187
        uint8_t rewrite_ttl;
188
        uint8_t rewrite_tos;
189
    } ipv4;
190
    struct {
191
        struct in6_addr ipv6_src;
192
        struct in6_addr ipv6_dst;
193
        uint8_t rewrite_hlimit;
194
        uint8_t rewrite_tclass;
195
    } ipv6;
196
197
    struct tc_flower_tunnel tunnel;
198
};
199
200
enum tc_action_type {
201
    TC_ACT_OUTPUT,
202
    TC_ACT_ENCAP,
203
    TC_ACT_PEDIT,
204
    TC_ACT_VLAN_POP,
205
    TC_ACT_VLAN_PUSH,
206
    TC_ACT_MPLS_POP,
207
    TC_ACT_MPLS_PUSH,
208
    TC_ACT_MPLS_SET,
209
    TC_ACT_GOTO,
210
    TC_ACT_CT,
211
    TC_ACT_POLICE,
212
    TC_ACT_POLICE_MTU,
213
};
214
215
enum nat_type {
216
    TC_NO_NAT = 0,
217
    TC_NAT_SRC,
218
    TC_NAT_DST,
219
    TC_NAT_RESTORE,
220
};
221
222
struct tc_action_encap {
223
    bool id_present;
224
    ovs_be64 id;
225
    /* ovs_be16 tp_src;  Could have been here, but there is no
226
     * TCA_TUNNEL_KEY_ENC_ attribute for it in the kernel. */
227
    ovs_be16 tp_dst;
228
    uint8_t tos;
229
    uint8_t ttl;
230
    uint8_t no_csum;
231
    bool dont_fragment;
232
    struct {
233
        ovs_be32 ipv4_src;
234
        ovs_be32 ipv4_dst;
235
    } ipv4;
236
    struct {
237
        struct in6_addr ipv6_src;
238
        struct in6_addr ipv6_dst;
239
    } ipv6;
240
    struct tun_metadata data;
241
    struct tc_tunnel_gbp gbp;
242
};
243
244
struct tc_action {
245
    union {
246
        int chain;
247
248
        struct {
249
            int ifindex_out;
250
            bool ingress;
251
        } out;
252
253
        struct {
254
            ovs_be16 vlan_push_tpid;
255
            uint16_t vlan_push_id;
256
            uint8_t vlan_push_prio;
257
        } vlan;
258
259
        struct {
260
            ovs_be16 proto;
261
            uint32_t label;
262
            uint8_t tc;
263
            uint8_t ttl;
264
            uint8_t bos;
265
        } mpls;
266
267
        struct tc_action_encap encap;
268
269
        struct {
270
            uint16_t zone;
271
            uint32_t mark;
272
            uint32_t mark_mask;
273
            ovs_u128 label;
274
            ovs_u128 label_mask;
275
            uint8_t nat_type;
276
            struct {
277
                uint8_t ip_family;
278
279
                union {
280
                    struct {
281
                        ovs_be32 min;
282
                        ovs_be32 max;
283
                    } ipv4;
284
                    struct {
285
                        struct in6_addr min;
286
                        struct in6_addr max;
287
                    } ipv6;
288
                };
289
290
                struct {
291
                    ovs_be16 min;
292
                    ovs_be16 max;
293
                } port;
294
295
            } range;
296
            bool clear;
297
            bool force;
298
            bool commit;
299
        } ct;
300
        struct {
301
            struct tc_flower_key key;
302
            struct tc_flower_key mask;
303
        } rewrite;
304
        struct {
305
            uint32_t index;
306
            uint32_t result_jump;
307
            uint16_t mtu;
308
        } police;
309
    };
310
311
    enum tc_action_type type;
312
    uint32_t jump_action;
313
0
#define JUMP_ACTION_STOP 0xffffffff
314
};
315
316
/* assert that if we overflow with a masked write of uint32_t to the last byte
317
 * of action.rewrite we overflow inside struct tc_action.
318
 * shouldn't happen unless someone moves rewrite to the end of action */
319
BUILD_ASSERT_DECL(offsetof(struct tc_action, rewrite)
320
                  + MEMBER_SIZEOF(struct tc_action, rewrite)
321
                  + sizeof(uint32_t) - 2 < sizeof(struct tc_action));
322
323
enum tc_offloaded_state {
324
    TC_OFFLOADED_STATE_UNDEFINED,
325
    TC_OFFLOADED_STATE_IN_HW,
326
    TC_OFFLOADED_STATE_NOT_IN_HW,
327
};
328
329
0
#define TCA_ACT_MAX_NUM 16
330
331
struct tcf_id {
332
    enum tc_qdisc_hook hook;
333
    uint32_t block_id;
334
    int ifindex;
335
    uint32_t chain;
336
    uint16_t prio;
337
    uint32_t handle;
338
};
339
340
static inline struct tcf_id
341
tc_make_tcf_id(int ifindex, uint32_t block_id, uint16_t prio,
342
               enum tc_qdisc_hook hook)
343
0
{
344
0
    struct tcf_id id = {
345
0
        .hook = hook,
346
0
        .block_id = block_id,
347
0
        .ifindex = ifindex,
348
0
        .prio = prio,
349
0
    };
350
351
0
    return id;
352
0
}
Unexecuted instantiation: netdev.c:tc_make_tcf_id
Unexecuted instantiation: netdev-linux.c:tc_make_tcf_id
Unexecuted instantiation: netdev-offload-tc.c:tc_make_tcf_id
Unexecuted instantiation: tc.c:tc_make_tcf_id
Unexecuted instantiation: netdev-offload.c:tc_make_tcf_id
353
354
static inline struct tcf_id
355
tc_make_tcf_id_chain(int ifindex, uint32_t block_id, uint32_t chain,
356
                     uint16_t prio, enum tc_qdisc_hook hook)
357
0
{
358
0
    struct tcf_id id = tc_make_tcf_id(ifindex, block_id, prio, hook);
359
360
0
    id.chain = chain;
361
362
0
    return id;
363
0
}
Unexecuted instantiation: netdev.c:tc_make_tcf_id_chain
Unexecuted instantiation: netdev-linux.c:tc_make_tcf_id_chain
Unexecuted instantiation: netdev-offload-tc.c:tc_make_tcf_id_chain
Unexecuted instantiation: tc.c:tc_make_tcf_id_chain
Unexecuted instantiation: netdev-offload.c:tc_make_tcf_id_chain
364
365
static inline bool
366
is_tcf_id_eq(struct tcf_id *id1, struct tcf_id *id2)
367
0
{
368
0
    return id1->prio == id2->prio
369
0
           && id1->handle == id2->handle
370
0
           && id1->hook == id2->hook
371
0
           && id1->block_id == id2->block_id
372
0
           && id1->ifindex == id2->ifindex
373
0
           && id1->chain == id2->chain;
374
0
}
Unexecuted instantiation: netdev.c:is_tcf_id_eq
Unexecuted instantiation: netdev-linux.c:is_tcf_id_eq
Unexecuted instantiation: netdev-offload-tc.c:is_tcf_id_eq
Unexecuted instantiation: tc.c:is_tcf_id_eq
Unexecuted instantiation: netdev-offload.c:is_tcf_id_eq
375
376
enum tc_offload_policy {
377
    TC_POLICY_NONE = 0,
378
    TC_POLICY_SKIP_SW,
379
    TC_POLICY_SKIP_HW
380
};
381
382
BUILD_ASSERT_DECL(TC_POLICY_NONE == 0);
383
384
struct tc_flower {
385
    struct tc_flower_key key;
386
    struct tc_flower_key mask;
387
388
    int action_count;
389
    struct tc_action actions[TCA_ACT_MAX_NUM];
390
391
    struct ovs_flow_stats stats_sw;
392
    struct ovs_flow_stats stats_hw;
393
    uint64_t lastused;
394
395
    uint32_t csum_update_flags;
396
397
    bool tunnel;
398
399
    struct tc_cookie act_cookie;
400
401
    bool needs_full_ip_proto_mask;
402
403
    enum tc_offloaded_state offloaded_state;
404
    /* Used to force skip_hw when probing tc features. */
405
    enum tc_offload_policy tc_policy;
406
};
407
408
int tc_replace_flower(struct tcf_id *id, struct tc_flower *flower);
409
int tc_del_filter(struct tcf_id *id, const char *kind);
410
int tc_del_flower_filter(struct tcf_id *id);
411
int tc_get_flower(struct tcf_id *id, struct tc_flower *flower);
412
int tc_dump_flower_start(struct tcf_id *id, struct nl_dump *dump, bool terse);
413
int tc_dump_tc_chain_start(struct tcf_id *id, struct nl_dump *dump);
414
int parse_netlink_to_tc_flower(struct ofpbuf *reply,
415
                               struct tcf_id *id,
416
                               struct tc_flower *flower,
417
                               bool terse);
418
int parse_netlink_to_tc_chain(struct ofpbuf *reply, uint32_t *chain);
419
void tc_set_policy(const char *policy);
420
int tc_parse_action_stats(struct nlattr *action,
421
                          struct ovs_flow_stats *stats_sw,
422
                          struct ovs_flow_stats *stats_hw,
423
                          struct ovs_flow_stats *stats_dropped);
424
int tc_dump_tc_action_start(char *name, struct nl_dump *dump);
425
int parse_netlink_to_tc_policer(struct ofpbuf *reply, uint32_t police_idx[]);
426
427
void nl_msg_put_act_tc_policy_flag(struct ofpbuf *request);
428
429
#endif /* tc.h */