]> git.proxmox.com Git - ceph.git/blob - ceph/src/spdk/dpdk/drivers/net/bonding/rte_eth_bond_alb.c
import 15.2.0 Octopus source
[ceph.git] / ceph / src / spdk / dpdk / drivers / net / bonding / rte_eth_bond_alb.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2015 Intel Corporation
3 */
4
5 #include "rte_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 for (i = 0; i < hash_size; ++i)
16 hash ^= hash_start[i];
17
18 return hash;
19 }
20
21 static uint16_t
22 calculate_slave(struct bond_dev_private *internals)
23 {
24 uint16_t idx;
25
26 idx = (internals->mode6.last_slave + 1) % internals->active_slave_count;
27 internals->mode6.last_slave = idx;
28 return internals->active_slaves[idx];
29 }
30
31 int
32 bond_mode_alb_enable(struct rte_eth_dev *bond_dev)
33 {
34 struct bond_dev_private *internals = bond_dev->data->dev_private;
35 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 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 internals->mode6.last_slave = ALB_NULL_INDEX;
45 internals->mode6.ntt = 0;
46
47 /* Initialize memory pool for ARP packets to send */
48 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 snprintf(mem_name, sizeof(mem_name), "%s_ALB",
55 bond_dev->device->name);
56 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 if (internals->mode6.mempool == NULL) {
63 RTE_BOND_LOG(ERR, "%s: Failed to initialize ALB mempool.\n",
64 bond_dev->device->name);
65 goto mempool_alloc_error;
66 }
67 }
68
69 return 0;
70
71 mempool_alloc_error:
72 return -ENOMEM;
73 }
74
75 void bond_mode_alb_arp_recv(struct ether_hdr *eth_h, uint16_t offset,
76 struct bond_dev_private *internals) {
77 struct arp_hdr *arp;
78
79 struct client_data *hash_table = internals->mode6.client_table;
80 struct client_data *client_info;
81
82 uint8_t hash_index;
83
84 arp = (struct arp_hdr *) ((char *) (eth_h + 1) + offset);
85
86 /* ARP Requests are forwarded to the application with no changes */
87 if (arp->arp_op != rte_cpu_to_be_16(ARP_OP_REPLY))
88 return;
89
90 /* From now on, we analyze only ARP Reply packets */
91 hash_index = simple_hash((uint8_t *) &arp->arp_data.arp_sip,
92 sizeof(arp->arp_data.arp_sip));
93 client_info = &hash_table[hash_index];
94
95 /*
96 * We got reply for ARP Request send by the application. We need to
97 * update client table when received data differ from what is stored
98 * in ALB table and issue sending update packet to that slave.
99 */
100 rte_spinlock_lock(&internals->mode6.lock);
101 if (client_info->in_use == 0 ||
102 client_info->app_ip != arp->arp_data.arp_tip ||
103 client_info->cli_ip != arp->arp_data.arp_sip ||
104 !is_same_ether_addr(&client_info->cli_mac, &arp->arp_data.arp_sha) ||
105 client_info->vlan_count != offset / sizeof(struct vlan_hdr) ||
106 memcmp(client_info->vlan, eth_h + 1, offset) != 0
107 ) {
108 client_info->in_use = 1;
109 client_info->app_ip = arp->arp_data.arp_tip;
110 client_info->cli_ip = arp->arp_data.arp_sip;
111 ether_addr_copy(&arp->arp_data.arp_sha, &client_info->cli_mac);
112 client_info->slave_idx = calculate_slave(internals);
113 rte_eth_macaddr_get(client_info->slave_idx, &client_info->app_mac);
114 ether_addr_copy(&client_info->app_mac, &arp->arp_data.arp_tha);
115 memcpy(client_info->vlan, eth_h + 1, offset);
116 client_info->vlan_count = offset / sizeof(struct vlan_hdr);
117 }
118 internals->mode6.ntt = 1;
119 rte_spinlock_unlock(&internals->mode6.lock);
120 }
121
122 uint16_t
123 bond_mode_alb_arp_xmit(struct ether_hdr *eth_h, uint16_t offset,
124 struct bond_dev_private *internals)
125 {
126 struct arp_hdr *arp;
127
128 struct client_data *hash_table = internals->mode6.client_table;
129 struct client_data *client_info;
130
131 uint8_t hash_index;
132
133 struct ether_addr bonding_mac;
134
135 arp = (struct arp_hdr *)((char *)(eth_h + 1) + offset);
136
137 /*
138 * Traffic with src MAC other than bonding should be sent on
139 * current primary port.
140 */
141 rte_eth_macaddr_get(internals->port_id, &bonding_mac);
142 if (!is_same_ether_addr(&bonding_mac, &arp->arp_data.arp_sha)) {
143 rte_eth_macaddr_get(internals->current_primary_port,
144 &arp->arp_data.arp_sha);
145 return internals->current_primary_port;
146 }
147
148 hash_index = simple_hash((uint8_t *)&arp->arp_data.arp_tip,
149 sizeof(uint32_t));
150 client_info = &hash_table[hash_index];
151
152 rte_spinlock_lock(&internals->mode6.lock);
153 if (arp->arp_op == rte_cpu_to_be_16(ARP_OP_REPLY)) {
154 if (client_info->in_use) {
155 if (client_info->app_ip == arp->arp_data.arp_sip &&
156 client_info->cli_ip == arp->arp_data.arp_tip) {
157 /* Entry is already assigned to this client */
158 if (!is_broadcast_ether_addr(&arp->arp_data.arp_tha)) {
159 ether_addr_copy(&arp->arp_data.arp_tha,
160 &client_info->cli_mac);
161 }
162 rte_eth_macaddr_get(client_info->slave_idx,
163 &client_info->app_mac);
164 ether_addr_copy(&client_info->app_mac, &arp->arp_data.arp_sha);
165 memcpy(client_info->vlan, eth_h + 1, offset);
166 client_info->vlan_count = offset / sizeof(struct vlan_hdr);
167 rte_spinlock_unlock(&internals->mode6.lock);
168 return client_info->slave_idx;
169 }
170 }
171
172 /* Assign new slave to this client and update src mac in ARP */
173 client_info->in_use = 1;
174 client_info->ntt = 0;
175 client_info->app_ip = arp->arp_data.arp_sip;
176 ether_addr_copy(&arp->arp_data.arp_tha, &client_info->cli_mac);
177 client_info->cli_ip = arp->arp_data.arp_tip;
178 client_info->slave_idx = calculate_slave(internals);
179 rte_eth_macaddr_get(client_info->slave_idx, &client_info->app_mac);
180 ether_addr_copy(&client_info->app_mac, &arp->arp_data.arp_sha);
181 memcpy(client_info->vlan, eth_h + 1, offset);
182 client_info->vlan_count = offset / sizeof(struct vlan_hdr);
183 rte_spinlock_unlock(&internals->mode6.lock);
184 return client_info->slave_idx;
185 }
186
187 /* If packet is not ARP Reply, send it on current primary port. */
188 rte_spinlock_unlock(&internals->mode6.lock);
189 rte_eth_macaddr_get(internals->current_primary_port,
190 &arp->arp_data.arp_sha);
191 return internals->current_primary_port;
192 }
193
194 uint16_t
195 bond_mode_alb_arp_upd(struct client_data *client_info,
196 struct rte_mbuf *pkt, struct bond_dev_private *internals)
197 {
198 struct ether_hdr *eth_h;
199 struct arp_hdr *arp_h;
200 uint16_t slave_idx;
201
202 rte_spinlock_lock(&internals->mode6.lock);
203 eth_h = rte_pktmbuf_mtod(pkt, struct ether_hdr *);
204
205 ether_addr_copy(&client_info->app_mac, &eth_h->s_addr);
206 ether_addr_copy(&client_info->cli_mac, &eth_h->d_addr);
207 if (client_info->vlan_count > 0)
208 eth_h->ether_type = rte_cpu_to_be_16(ETHER_TYPE_VLAN);
209 else
210 eth_h->ether_type = rte_cpu_to_be_16(ETHER_TYPE_ARP);
211
212 arp_h = (struct arp_hdr *)((char *)eth_h + sizeof(struct ether_hdr)
213 + client_info->vlan_count * sizeof(struct vlan_hdr));
214
215 memcpy(eth_h + 1, client_info->vlan,
216 client_info->vlan_count * sizeof(struct vlan_hdr));
217
218 ether_addr_copy(&client_info->app_mac, &arp_h->arp_data.arp_sha);
219 arp_h->arp_data.arp_sip = client_info->app_ip;
220 ether_addr_copy(&client_info->cli_mac, &arp_h->arp_data.arp_tha);
221 arp_h->arp_data.arp_tip = client_info->cli_ip;
222
223 arp_h->arp_hrd = rte_cpu_to_be_16(ARP_HRD_ETHER);
224 arp_h->arp_pro = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
225 arp_h->arp_hln = ETHER_ADDR_LEN;
226 arp_h->arp_pln = sizeof(uint32_t);
227 arp_h->arp_op = rte_cpu_to_be_16(ARP_OP_REPLY);
228
229 slave_idx = client_info->slave_idx;
230 rte_spinlock_unlock(&internals->mode6.lock);
231
232 return slave_idx;
233 }
234
235 void
236 bond_mode_alb_client_list_upd(struct rte_eth_dev *bond_dev)
237 {
238 struct bond_dev_private *internals = bond_dev->data->dev_private;
239 struct client_data *client_info;
240
241 int i;
242
243 /* If active slave count is 0, it's pointless to refresh alb table */
244 if (internals->active_slave_count <= 0)
245 return;
246
247 rte_spinlock_lock(&internals->mode6.lock);
248 internals->mode6.last_slave = ALB_NULL_INDEX;
249
250 for (i = 0; i < ALB_HASH_TABLE_SIZE; i++) {
251 client_info = &internals->mode6.client_table[i];
252 if (client_info->in_use) {
253 client_info->slave_idx = calculate_slave(internals);
254 rte_eth_macaddr_get(client_info->slave_idx, &client_info->app_mac);
255 internals->mode6.ntt = 1;
256 }
257 }
258 rte_spinlock_unlock(&internals->mode6.lock);
259 }