Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2010-2015 Intel Corporation
3 : : */
4 : :
5 : : #include "eth_bond_private.h"
6 : : #include "rte_eth_bond_alb.h"
7 : :
8 : : static inline uint8_t
9 : : simple_hash(uint8_t *hash_start, int hash_size)
10 : : {
11 : : int i;
12 : : uint8_t hash;
13 : :
14 : : hash = 0;
15 [ # # # # ]: 0 : for (i = 0; i < hash_size; ++i)
16 : 0 : hash ^= hash_start[i];
17 : :
18 : : return hash;
19 : : }
20 : :
21 : : static uint16_t
22 : : calculate_member(struct bond_dev_private *internals)
23 : : {
24 : : uint16_t idx;
25 : :
26 : 0 : idx = (internals->mode6.last_member + 1) % internals->active_member_count;
27 : 0 : internals->mode6.last_member = idx;
28 : 0 : return internals->active_members[idx];
29 : : }
30 : :
31 : : int
32 : 0 : bond_mode_alb_enable(struct rte_eth_dev *bond_dev)
33 : : {
34 : 0 : struct bond_dev_private *internals = bond_dev->data->dev_private;
35 : 0 : struct client_data *hash_table = internals->mode6.client_table;
36 : :
37 : : uint16_t data_size;
38 : : char mem_name[RTE_ETH_NAME_MAX_LEN];
39 [ # # ]: 0 : int socket_id = bond_dev->data->numa_node;
40 : :
41 : : /* Fill hash table with initial values */
42 : : memset(hash_table, 0, sizeof(struct client_data) * ALB_HASH_TABLE_SIZE);
43 : : rte_spinlock_init(&internals->mode6.lock);
44 : 0 : internals->mode6.last_member = ALB_NULL_INDEX;
45 : 0 : internals->mode6.ntt = 0;
46 : :
47 : : /* Initialize memory pool for ARP packets to send */
48 [ # # ]: 0 : if (internals->mode6.mempool == NULL) {
49 : : /*
50 : : * 256 is size of ETH header, ARP header and nested VLAN headers.
51 : : * The value is chosen to be cache aligned.
52 : : */
53 : : data_size = 256 + RTE_PKTMBUF_HEADROOM;
54 : 0 : snprintf(mem_name, sizeof(mem_name), "%s_ALB",
55 : 0 : bond_dev->device->name);
56 : 0 : internals->mode6.mempool = rte_pktmbuf_pool_create(mem_name,
57 : : 512 * RTE_MAX_ETHPORTS,
58 : : RTE_MEMPOOL_CACHE_MAX_SIZE >= 32 ?
59 : : 32 : RTE_MEMPOOL_CACHE_MAX_SIZE,
60 : : 0, data_size, socket_id);
61 : :
62 [ # # ]: 0 : if (internals->mode6.mempool == NULL) {
63 : 0 : RTE_BOND_LOG(ERR, "%s: Failed to initialize ALB mempool.\n",
64 : : bond_dev->device->name);
65 : 0 : goto mempool_alloc_error;
66 : : }
67 : : }
68 : :
69 : : return 0;
70 : :
71 : : mempool_alloc_error:
72 : 0 : return -ENOMEM;
73 : : }
74 : :
75 : 0 : void bond_mode_alb_arp_recv(struct rte_ether_hdr *eth_h, uint16_t offset,
76 : : struct bond_dev_private *internals)
77 : : {
78 : : struct rte_arp_hdr *arp;
79 : :
80 : 0 : struct client_data *hash_table = internals->mode6.client_table;
81 : : struct client_data *client_info;
82 : :
83 : : uint8_t hash_index;
84 : :
85 : 0 : arp = (struct rte_arp_hdr *)((char *)(eth_h + 1) + offset);
86 : :
87 : : /* ARP Requests are forwarded to the application with no changes */
88 [ # # ]: 0 : if (arp->arp_opcode != rte_cpu_to_be_16(RTE_ARP_OP_REPLY))
89 : : return;
90 : :
91 : : /* From now on, we analyze only ARP Reply packets */
92 : 0 : hash_index = simple_hash((uint8_t *) &arp->arp_data.arp_sip,
93 : : sizeof(arp->arp_data.arp_sip));
94 : 0 : client_info = &hash_table[hash_index];
95 : :
96 : : /*
97 : : * We got reply for ARP Request send by the application. We need to
98 : : * update client table when received data differ from what is stored
99 : : * in ALB table and issue sending update packet to that member.
100 : : */
101 : 0 : rte_spinlock_lock(&internals->mode6.lock);
102 [ # # ]: 0 : if (client_info->in_use == 0 ||
103 [ # # ]: 0 : client_info->app_ip != arp->arp_data.arp_tip ||
104 [ # # # # ]: 0 : client_info->cli_ip != arp->arp_data.arp_sip ||
105 : : !rte_is_same_ether_addr(&client_info->cli_mac,
106 : 0 : &arp->arp_data.arp_sha) ||
107 [ # # ]: 0 : client_info->vlan_count != offset / sizeof(struct rte_vlan_hdr) ||
108 [ # # ]: 0 : memcmp(client_info->vlan, eth_h + 1, offset) != 0
109 : : ) {
110 : 0 : client_info->in_use = 1;
111 : 0 : client_info->app_ip = arp->arp_data.arp_tip;
112 : 0 : client_info->cli_ip = arp->arp_data.arp_sip;
113 : : rte_ether_addr_copy(&arp->arp_data.arp_sha,
114 : : &client_info->cli_mac);
115 : 0 : client_info->member_idx = calculate_member(internals);
116 : 0 : rte_eth_macaddr_get(client_info->member_idx,
117 : : &client_info->app_mac);
118 : : rte_ether_addr_copy(&client_info->app_mac,
119 : : &arp->arp_data.arp_tha);
120 : 0 : memcpy(client_info->vlan, eth_h + 1, offset);
121 : 0 : client_info->vlan_count = offset / sizeof(struct rte_vlan_hdr);
122 : : }
123 : 0 : internals->mode6.ntt = 1;
124 : : rte_spinlock_unlock(&internals->mode6.lock);
125 : : }
126 : :
127 : : uint16_t
128 : 0 : bond_mode_alb_arp_xmit(struct rte_ether_hdr *eth_h, uint16_t offset,
129 : : struct bond_dev_private *internals)
130 : : {
131 : : struct rte_arp_hdr *arp;
132 : :
133 : 0 : struct client_data *hash_table = internals->mode6.client_table;
134 : : struct client_data *client_info;
135 : :
136 : : uint8_t hash_index;
137 : :
138 : : struct rte_ether_addr bonding_mac;
139 : :
140 : 0 : arp = (struct rte_arp_hdr *)((char *)(eth_h + 1) + offset);
141 : :
142 : : /*
143 : : * Traffic with src MAC other than bonding should be sent on
144 : : * current primary port.
145 : : */
146 : 0 : rte_eth_macaddr_get(internals->port_id, &bonding_mac);
147 [ # # ]: 0 : if (!rte_is_same_ether_addr(&bonding_mac, &arp->arp_data.arp_sha)) {
148 : 0 : rte_eth_macaddr_get(internals->current_primary_port,
149 : : &arp->arp_data.arp_sha);
150 : 0 : return internals->current_primary_port;
151 : : }
152 : :
153 : 0 : hash_index = simple_hash((uint8_t *)&arp->arp_data.arp_tip,
154 : : sizeof(uint32_t));
155 : 0 : client_info = &hash_table[hash_index];
156 : :
157 : 0 : rte_spinlock_lock(&internals->mode6.lock);
158 [ # # ]: 0 : if (arp->arp_opcode == rte_cpu_to_be_16(RTE_ARP_OP_REPLY)) {
159 [ # # ]: 0 : if (client_info->in_use) {
160 [ # # ]: 0 : if (client_info->app_ip == arp->arp_data.arp_sip &&
161 [ # # ]: 0 : client_info->cli_ip == arp->arp_data.arp_tip) {
162 : : /* Entry is already assigned to this client */
163 [ # # ]: 0 : if (!rte_is_broadcast_ether_addr(
164 : : &arp->arp_data.arp_tha)) {
165 : : rte_ether_addr_copy(
166 : : &arp->arp_data.arp_tha,
167 : : &client_info->cli_mac);
168 : : }
169 : 0 : rte_eth_macaddr_get(client_info->member_idx,
170 : : &client_info->app_mac);
171 : : rte_ether_addr_copy(&client_info->app_mac,
172 : : &arp->arp_data.arp_sha);
173 : 0 : memcpy(client_info->vlan, eth_h + 1, offset);
174 : 0 : client_info->vlan_count = offset / sizeof(struct rte_vlan_hdr);
175 : : rte_spinlock_unlock(&internals->mode6.lock);
176 : 0 : return client_info->member_idx;
177 : : }
178 : : }
179 : :
180 : : /* Assign new member to this client and update src mac in ARP */
181 : 0 : client_info->in_use = 1;
182 : 0 : client_info->ntt = 0;
183 : 0 : client_info->app_ip = arp->arp_data.arp_sip;
184 : : rte_ether_addr_copy(&arp->arp_data.arp_tha,
185 : : &client_info->cli_mac);
186 : 0 : client_info->cli_ip = arp->arp_data.arp_tip;
187 : 0 : client_info->member_idx = calculate_member(internals);
188 : 0 : rte_eth_macaddr_get(client_info->member_idx,
189 : : &client_info->app_mac);
190 : : rte_ether_addr_copy(&client_info->app_mac,
191 : : &arp->arp_data.arp_sha);
192 : 0 : memcpy(client_info->vlan, eth_h + 1, offset);
193 : 0 : client_info->vlan_count = offset / sizeof(struct rte_vlan_hdr);
194 : : rte_spinlock_unlock(&internals->mode6.lock);
195 : 0 : return client_info->member_idx;
196 : : }
197 : :
198 : : /* If packet is not ARP Reply, send it on current primary port. */
199 : : rte_spinlock_unlock(&internals->mode6.lock);
200 : 0 : rte_eth_macaddr_get(internals->current_primary_port,
201 : : &arp->arp_data.arp_sha);
202 : 0 : return internals->current_primary_port;
203 : : }
204 : :
205 : : uint16_t
206 : 0 : bond_mode_alb_arp_upd(struct client_data *client_info,
207 : : struct rte_mbuf *pkt, struct bond_dev_private *internals)
208 : : {
209 : : struct rte_ether_hdr *eth_h;
210 : : struct rte_arp_hdr *arp_h;
211 : : uint16_t member_idx;
212 : :
213 : 0 : rte_spinlock_lock(&internals->mode6.lock);
214 [ # # ]: 0 : eth_h = rte_pktmbuf_mtod(pkt, struct rte_ether_hdr *);
215 : :
216 : : rte_ether_addr_copy(&client_info->app_mac, ð_h->src_addr);
217 : : rte_ether_addr_copy(&client_info->cli_mac, ð_h->dst_addr);
218 [ # # ]: 0 : if (client_info->vlan_count > 0)
219 : 0 : eth_h->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
220 : : else
221 : 0 : eth_h->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_ARP);
222 : :
223 : 0 : arp_h = (struct rte_arp_hdr *)(
224 : : (char *)eth_h + sizeof(struct rte_ether_hdr)
225 : 0 : + client_info->vlan_count * sizeof(struct rte_vlan_hdr));
226 : :
227 : 0 : memcpy(eth_h + 1, client_info->vlan,
228 : : client_info->vlan_count * sizeof(struct rte_vlan_hdr));
229 : :
230 : : rte_ether_addr_copy(&client_info->app_mac, &arp_h->arp_data.arp_sha);
231 : 0 : arp_h->arp_data.arp_sip = client_info->app_ip;
232 : : rte_ether_addr_copy(&client_info->cli_mac, &arp_h->arp_data.arp_tha);
233 : 0 : arp_h->arp_data.arp_tip = client_info->cli_ip;
234 : :
235 : 0 : arp_h->arp_hardware = rte_cpu_to_be_16(RTE_ARP_HRD_ETHER);
236 : 0 : arp_h->arp_protocol = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
237 : 0 : arp_h->arp_hlen = RTE_ETHER_ADDR_LEN;
238 : 0 : arp_h->arp_plen = sizeof(uint32_t);
239 : 0 : arp_h->arp_opcode = rte_cpu_to_be_16(RTE_ARP_OP_REPLY);
240 : :
241 : 0 : member_idx = client_info->member_idx;
242 : : rte_spinlock_unlock(&internals->mode6.lock);
243 : :
244 : 0 : return member_idx;
245 : : }
246 : :
247 : : void
248 : 0 : bond_mode_alb_client_list_upd(struct rte_eth_dev *bond_dev)
249 : : {
250 : 0 : struct bond_dev_private *internals = bond_dev->data->dev_private;
251 : : struct client_data *client_info;
252 : :
253 : : int i;
254 : :
255 : : /* If active member count is 0, it's pointless to refresh alb table */
256 [ # # ]: 0 : if (internals->active_member_count <= 0)
257 : : return;
258 : :
259 : 0 : rte_spinlock_lock(&internals->mode6.lock);
260 : 0 : internals->mode6.last_member = ALB_NULL_INDEX;
261 : :
262 [ # # ]: 0 : for (i = 0; i < ALB_HASH_TABLE_SIZE; i++) {
263 : : client_info = &internals->mode6.client_table[i];
264 [ # # ]: 0 : if (client_info->in_use) {
265 : 0 : client_info->member_idx = calculate_member(internals);
266 : 0 : rte_eth_macaddr_get(client_info->member_idx, &client_info->app_mac);
267 : 0 : internals->mode6.ntt = 1;
268 : : }
269 : : }
270 : : rte_spinlock_unlock(&internals->mode6.lock);
271 : : }
|