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,
43 : uint16_t rx_q,
44 : uint32_t src_ip,
45 : uint32_t src_mask,
46 : uint32_t dest_ip,
47 : uint32_t dest_mask,
48 : struct rte_flow_error* error)
49 : {
50 : // Declaring structs being used.
51 0 : struct rte_flow_attr attr;
52 0 : struct rte_flow_item pattern[MAX_PATTERN_NUM];
53 0 : struct rte_flow_action action[MAX_ACTION_NUM];
54 0 : struct rte_flow* flow = NULL;
55 0 : struct rte_flow_action_queue queue = { .index = rx_q };
56 0 : struct rte_flow_item_ipv4 ip_spec;
57 0 : struct rte_flow_item_ipv4 ip_mask;
58 :
59 0 : int res;
60 :
61 0 : memset(pattern, 0, sizeof(pattern));
62 0 : memset(action, 0, sizeof(action));
63 :
64 : // Set the rule attribute, only ingress packets will be checked.
65 0 : memset(&attr, 0, sizeof(struct rte_flow_attr));
66 0 : attr.ingress = 1;
67 :
68 : /*
69 : * create the action sequence.
70 : * one action only, move packet to queue
71 : */
72 0 : action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
73 0 : action[0].conf = &queue;
74 0 : action[1].type = RTE_FLOW_ACTION_TYPE_END;
75 :
76 : /*
77 : * set the first level of the pattern (ETH).
78 : * since in this example we just want to get the
79 : * ipv4 we set this level to allow all.
80 : */
81 :
82 : // Set this level to allow all.
83 :
84 : /*
85 : * setting the second level of the pattern (IP).
86 : * in this example this is the level we care about
87 : * so we set it according to the parameters.
88 : */
89 :
90 : // Setting the second level of the pattern.
91 0 : memset(&ip_spec, 0, sizeof(struct rte_flow_item_ipv4));
92 0 : memset(&ip_mask, 0, sizeof(struct rte_flow_item_ipv4));
93 0 : ip_spec.hdr.dst_addr = htonl(dest_ip);
94 0 : ip_mask.hdr.dst_addr = 0;
95 0 : ip_spec.hdr.src_addr = htonl(src_ip);
96 0 : ip_mask.hdr.src_addr = src_mask;
97 :
98 0 : pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
99 :
100 0 : pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
101 0 : pattern[1].spec = &ip_spec;
102 0 : pattern[1].mask = &ip_mask;
103 :
104 0 : pattern[2].type = RTE_FLOW_ITEM_TYPE_END;
105 :
106 : // Validate the rule and create it.
107 0 : res = rte_flow_validate(port_id, &attr, pattern, action, error);
108 0 : if (not res) {
109 0 : flow = rte_flow_create(port_id, &attr, pattern, action, error);
110 : }
111 :
112 0 : return flow;
113 : }
114 :
115 : // Droppign all the traffic that did pass a flow with higher priority
116 : struct rte_flow*
117 0 : generate_drop_flow(uint16_t port_id, struct rte_flow_error* error)
118 : {
119 0 : struct rte_flow_attr attr;
120 0 : struct rte_flow_item pattern[MAX_PATTERN_NUM];
121 0 : struct rte_flow_action action[MAX_ACTION_NUM];
122 0 : struct rte_flow* flow = NULL;
123 0 : int res;
124 :
125 0 : memset(pattern, 0, sizeof(pattern));
126 0 : memset(action, 0, sizeof(action));
127 :
128 : // Set the rule attribute, only ingress packets will be checked.
129 0 : memset(&attr, 0, sizeof(struct rte_flow_attr));
130 0 : attr.ingress = 1;
131 0 : attr.egress = 0;
132 0 : attr.priority = 1; // TODO the higher the lower?
133 :
134 : /*
135 : * create the action sequence.
136 : * one action only, Drop the packet
137 : */
138 0 : action[0].type = RTE_FLOW_ACTION_TYPE_DROP;
139 0 : action[1].type = RTE_FLOW_ACTION_TYPE_END;
140 :
141 : /*
142 : * set the first level of the pattern (ETH).
143 : * since in this example we just want to get the
144 : * ipv4 we set this level to allow all.
145 : */
146 :
147 : // Set this level to allow all.
148 0 : pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
149 :
150 : /*
151 : * setting the second level of the pattern (IP).
152 : * in this example this is the level we care about
153 : * so we set it according to the parameters.
154 : */
155 :
156 : // The final level must be always type end.
157 0 : pattern[1].type = RTE_FLOW_ITEM_TYPE_END;
158 :
159 : // Validate the rule and create it.
160 0 : res = rte_flow_validate(port_id, &attr, pattern, action, error);
161 0 : if (not res) {
162 0 : flow = rte_flow_create(port_id, &attr, pattern, action, error);
163 : }
164 :
165 0 : return flow;
166 : }
167 :
168 : // ARP packets to specific
169 : struct rte_flow*
170 0 : generate_arp_flow(uint16_t port_id, uint16_t rx_q, struct rte_flow_error* error)
171 : {
172 0 : struct rte_flow_attr attr;
173 0 : struct rte_flow_item pattern[MAX_PATTERN_NUM];
174 0 : struct rte_flow_action action[MAX_ACTION_NUM];
175 0 : struct rte_flow* flow = NULL;
176 0 : struct rte_flow_action_queue queue = { .index = rx_q };
177 0 : int res;
178 :
179 0 : memset(pattern, 0, sizeof(pattern));
180 0 : memset(action, 0, sizeof(action));
181 :
182 : // Set the rule attribute, only ingress packets will be checked.
183 0 : memset(&attr, 0, sizeof(struct rte_flow_attr));
184 0 : attr.ingress = 1;
185 0 : attr.egress = 0;
186 0 : attr.priority = 1; // TODO the higher the lower?
187 :
188 : // Action -> queue steering
189 0 : action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
190 0 : action[0].conf = &queue;
191 0 : action[1].type = RTE_FLOW_ACTION_TYPE_END;
192 :
193 : // Rule prep
194 0 : struct rte_flow_item_eth item_eth_mask = {};
195 0 : struct rte_flow_item_eth item_eth_spec = {};
196 : // Rule marker
197 0 : item_eth_spec.hdr.ether_type = RTE_BE16(RTE_ETHER_TYPE_ARP);
198 0 : item_eth_mask.hdr.ether_type = RTE_BE16(0xFFFF);
199 : // Rule pattern
200 0 : pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
201 0 : pattern[0].mask = &item_eth_mask;
202 0 : pattern[0].spec = &item_eth_spec;
203 0 : pattern[1].type = RTE_FLOW_ITEM_TYPE_END;
204 :
205 : // Validate the rule and create it.
206 0 : res = rte_flow_validate(port_id, &attr, pattern, action, error);
207 0 : if (not res) {
208 0 : flow = rte_flow_create(port_id, &attr, pattern, action, error);
209 : }
210 :
211 0 : return flow;
212 : }
213 :
214 : } // namespace dpdklibs
215 : } // namespace dunedaq
|