Line data Source code
1 : /* SPDX-License-Identifier: BSD-3-Clause
2 : * Copyright 2017 Mellanox Technologies, Ltd
3 : */
4 :
5 : #include "dpdklibs/FlowControl.hpp"
6 :
7 : #include "logging/Logging.hpp"
8 :
9 : #include <rte_byteorder.h>
10 : #include <rte_ether.h>
11 : #include <rte_flow.h>
12 : #include <rte_ip.h>
13 :
14 : namespace dunedaq {
15 : namespace dpdklibs {
16 :
17 : /**
18 : * create a flow rule that sends packets with matching src and dest ip
19 : * to selected queue.
20 : *
21 : * @param port_id
22 : * The selected port.
23 : * @param rx_q
24 : * The selected target queue.
25 : * @param src_ip
26 : * The src ip value to match the input packet.
27 : * @param src_mask
28 : * The mask to apply to the src ip.
29 : * @param dest_ip
30 : * The dest ip value to match the input packet.
31 : * @param dest_mask
32 : * The mask to apply to the dest ip.
33 : * @param[out] error
34 : * Perform verbose error reporting if not NULL.
35 : *
36 : * @return
37 : * A flow if the rule could be created else return NULL.
38 : */
39 :
40 : /* Function responsible for creating the flow rule. 8< */
41 : struct rte_flow *
42 0 : generate_ipv4_flow(uint16_t port_id, uint16_t rx_q,
43 : uint32_t src_ip, uint32_t src_mask,
44 : uint32_t dest_ip, uint32_t dest_mask,
45 : struct rte_flow_error *error)
46 : {
47 : // Declaring structs being used.
48 0 : struct rte_flow_attr attr;
49 0 : struct rte_flow_item pattern[MAX_PATTERN_NUM];
50 0 : struct rte_flow_action action[MAX_ACTION_NUM];
51 0 : struct rte_flow *flow = NULL;
52 0 : struct rte_flow_action_queue queue = { .index = rx_q };
53 0 : struct rte_flow_item_ipv4 ip_spec;
54 0 : struct rte_flow_item_ipv4 ip_mask;
55 :
56 0 : int res;
57 :
58 0 : memset(pattern, 0, sizeof(pattern));
59 0 : memset(action, 0, sizeof(action));
60 :
61 : // Set the rule attribute, only ingress packets will be checked.
62 0 : memset(&attr, 0, sizeof(struct rte_flow_attr));
63 0 : attr.ingress = 1;
64 :
65 : /*
66 : * create the action sequence.
67 : * one action only, move packet to queue
68 : */
69 0 : action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
70 0 : action[0].conf = &queue;
71 0 : action[1].type = RTE_FLOW_ACTION_TYPE_END;
72 :
73 : /*
74 : * set the first level of the pattern (ETH).
75 : * since in this example we just want to get the
76 : * ipv4 we set this level to allow all.
77 : */
78 :
79 : // Set this level to allow all.
80 :
81 : /*
82 : * setting the second level of the pattern (IP).
83 : * in this example this is the level we care about
84 : * so we set it according to the parameters.
85 : */
86 :
87 : // Setting the second level of the pattern.
88 0 : memset(&ip_spec, 0, sizeof(struct rte_flow_item_ipv4));
89 0 : memset(&ip_mask, 0, sizeof(struct rte_flow_item_ipv4));
90 0 : ip_spec.hdr.dst_addr = htonl(dest_ip);
91 0 : ip_mask.hdr.dst_addr = 0;
92 0 : ip_spec.hdr.src_addr = htonl(src_ip);
93 0 : ip_mask.hdr.src_addr = src_mask;
94 :
95 0 : pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
96 :
97 0 : pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
98 0 : pattern[1].spec = &ip_spec;
99 0 : pattern[1].mask = &ip_mask;
100 :
101 :
102 0 : pattern[2].type = RTE_FLOW_ITEM_TYPE_END;
103 :
104 : // Validate the rule and create it.
105 0 : res = rte_flow_validate(port_id, &attr, pattern, action, error);
106 0 : if (not res) {
107 0 : flow = rte_flow_create(port_id, &attr, pattern, action, error);
108 : }
109 :
110 0 : return flow;
111 : }
112 :
113 : // Droppign all the traffic that did pass a flow with higher priority
114 : struct rte_flow *
115 0 : generate_drop_flow(uint16_t port_id, struct rte_flow_error *error)
116 : {
117 0 : struct rte_flow_attr attr;
118 0 : struct rte_flow_item pattern[MAX_PATTERN_NUM];
119 0 : struct rte_flow_action action[MAX_ACTION_NUM];
120 0 : struct rte_flow *flow = NULL;
121 0 : int res;
122 :
123 0 : memset(pattern, 0, sizeof(pattern));
124 0 : memset(action, 0, sizeof(action));
125 :
126 : // Set the rule attribute, only ingress packets will be checked.
127 0 : memset(&attr, 0, sizeof(struct rte_flow_attr));
128 0 : attr.ingress = 1;
129 0 : attr.egress = 0;
130 0 : attr.priority = 1; // TODO the higher the lower?
131 :
132 : /*
133 : * create the action sequence.
134 : * one action only, Drop the packet
135 : */
136 0 : action[0].type = RTE_FLOW_ACTION_TYPE_DROP;
137 0 : action[1].type = RTE_FLOW_ACTION_TYPE_END;
138 :
139 : /*
140 : * set the first level of the pattern (ETH).
141 : * since in this example we just want to get the
142 : * ipv4 we set this level to allow all.
143 : */
144 :
145 : // Set this level to allow all.
146 0 : pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
147 :
148 : /*
149 : * setting the second level of the pattern (IP).
150 : * in this example this is the level we care about
151 : * so we set it according to the parameters.
152 : */
153 :
154 : // The final level must be always type end.
155 0 : pattern[1].type = RTE_FLOW_ITEM_TYPE_END;
156 :
157 : // Validate the rule and create it.
158 0 : res = rte_flow_validate(port_id, &attr, pattern, action, error);
159 0 : if (not res) {
160 0 : flow = rte_flow_create(port_id, &attr, pattern, action, error);
161 : }
162 :
163 0 : return flow;
164 : }
165 :
166 : // ARP packets to specific
167 : struct rte_flow *
168 0 : generate_arp_flow(uint16_t port_id, uint16_t rx_q, struct rte_flow_error *error)
169 : {
170 0 : struct rte_flow_attr attr;
171 0 : struct rte_flow_item pattern[MAX_PATTERN_NUM];
172 0 : struct rte_flow_action action[MAX_ACTION_NUM];
173 0 : struct rte_flow *flow = NULL;
174 0 : struct rte_flow_action_queue queue = { .index = rx_q };
175 0 : int res;
176 :
177 0 : memset(pattern, 0, sizeof(pattern));
178 0 : memset(action, 0, sizeof(action));
179 :
180 : // Set the rule attribute, only ingress packets will be checked.
181 0 : memset(&attr, 0, sizeof(struct rte_flow_attr));
182 0 : attr.ingress = 1;
183 0 : attr.egress = 0;
184 0 : attr.priority = 1; // TODO the higher the lower?
185 :
186 : // Action -> queue steering
187 0 : action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
188 0 : action[0].conf = &queue;
189 0 : action[1].type = RTE_FLOW_ACTION_TYPE_END;
190 :
191 : // Rule prep
192 0 : struct rte_flow_item_eth item_eth_mask = {};
193 0 : struct rte_flow_item_eth item_eth_spec = {};
194 : // Rule marker
195 0 : item_eth_spec.hdr.ether_type = RTE_BE16(RTE_ETHER_TYPE_ARP);
196 0 : item_eth_mask.hdr.ether_type = RTE_BE16(0xFFFF);
197 : // Rule pattern
198 0 : pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
199 0 : pattern[0].mask = &item_eth_mask;
200 0 : pattern[0].spec = &item_eth_spec;
201 0 : pattern[1].type = RTE_FLOW_ITEM_TYPE_END;
202 :
203 : // Validate the rule and create it.
204 0 : res = rte_flow_validate(port_id, &attr, pattern, action, error);
205 0 : if (not res) {
206 0 : flow = rte_flow_create(port_id, &attr, pattern, action, error);
207 : }
208 :
209 0 : return flow;
210 : }
211 :
212 : } // namespace dpdklibs
213 : } // namespace dunedaq
|