net: add rte prefix to ether structures
[dpdk.git] / 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 rte_ether_hdr *eth_h, uint16_t offset,
76                 struct bond_dev_private *internals)
77 {
78         struct rte_arp_hdr *arp;
79
80         struct client_data *hash_table = internals->mode6.client_table;
81         struct client_data *client_info;
82
83         uint8_t hash_index;
84
85         arp = (struct rte_arp_hdr *)((char *)(eth_h + 1) + offset);
86
87         /* ARP Requests are forwarded to the application with no changes */
88         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         hash_index = simple_hash((uint8_t *) &arp->arp_data.arp_sip,
93                         sizeof(arp->arp_data.arp_sip));
94         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 slave.
100          */
101         rte_spinlock_lock(&internals->mode6.lock);
102         if (client_info->in_use == 0 ||
103                         client_info->app_ip != arp->arp_data.arp_tip ||
104                         client_info->cli_ip != arp->arp_data.arp_sip ||
105                         !is_same_ether_addr(&client_info->cli_mac, &arp->arp_data.arp_sha) ||
106                         client_info->vlan_count != offset / sizeof(struct rte_vlan_hdr) ||
107                         memcmp(client_info->vlan, eth_h + 1, offset) != 0
108         ) {
109                 client_info->in_use = 1;
110                 client_info->app_ip = arp->arp_data.arp_tip;
111                 client_info->cli_ip = arp->arp_data.arp_sip;
112                 ether_addr_copy(&arp->arp_data.arp_sha, &client_info->cli_mac);
113                 client_info->slave_idx = calculate_slave(internals);
114                 rte_eth_macaddr_get(client_info->slave_idx, &client_info->app_mac);
115                 ether_addr_copy(&client_info->app_mac, &arp->arp_data.arp_tha);
116                 memcpy(client_info->vlan, eth_h + 1, offset);
117                 client_info->vlan_count = offset / sizeof(struct rte_vlan_hdr);
118         }
119         internals->mode6.ntt = 1;
120         rte_spinlock_unlock(&internals->mode6.lock);
121 }
122
123 uint16_t
124 bond_mode_alb_arp_xmit(struct rte_ether_hdr *eth_h, uint16_t offset,
125                 struct bond_dev_private *internals)
126 {
127         struct rte_arp_hdr *arp;
128
129         struct client_data *hash_table = internals->mode6.client_table;
130         struct client_data *client_info;
131
132         uint8_t hash_index;
133
134         struct rte_ether_addr bonding_mac;
135
136         arp = (struct rte_arp_hdr *)((char *)(eth_h + 1) + offset);
137
138         /*
139          * Traffic with src MAC other than bonding should be sent on
140          * current primary port.
141          */
142         rte_eth_macaddr_get(internals->port_id, &bonding_mac);
143         if (!is_same_ether_addr(&bonding_mac, &arp->arp_data.arp_sha)) {
144                 rte_eth_macaddr_get(internals->current_primary_port,
145                                 &arp->arp_data.arp_sha);
146                 return internals->current_primary_port;
147         }
148
149         hash_index = simple_hash((uint8_t *)&arp->arp_data.arp_tip,
150                         sizeof(uint32_t));
151         client_info = &hash_table[hash_index];
152
153         rte_spinlock_lock(&internals->mode6.lock);
154         if (arp->arp_opcode == rte_cpu_to_be_16(RTE_ARP_OP_REPLY)) {
155                 if (client_info->in_use) {
156                         if (client_info->app_ip == arp->arp_data.arp_sip &&
157                                 client_info->cli_ip == arp->arp_data.arp_tip) {
158                                 /* Entry is already assigned to this client */
159                                 if (!is_broadcast_ether_addr(&arp->arp_data.arp_tha)) {
160                                         ether_addr_copy(&arp->arp_data.arp_tha,
161                                                         &client_info->cli_mac);
162                                 }
163                                 rte_eth_macaddr_get(client_info->slave_idx,
164                                                 &client_info->app_mac);
165                                 ether_addr_copy(&client_info->app_mac, &arp->arp_data.arp_sha);
166                                 memcpy(client_info->vlan, eth_h + 1, offset);
167                                 client_info->vlan_count = offset / sizeof(struct rte_vlan_hdr);
168                                 rte_spinlock_unlock(&internals->mode6.lock);
169                                 return client_info->slave_idx;
170                         }
171                 }
172
173                 /* Assign new slave to this client and update src mac in ARP */
174                 client_info->in_use = 1;
175                 client_info->ntt = 0;
176                 client_info->app_ip = arp->arp_data.arp_sip;
177                 ether_addr_copy(&arp->arp_data.arp_tha, &client_info->cli_mac);
178                 client_info->cli_ip = arp->arp_data.arp_tip;
179                 client_info->slave_idx = calculate_slave(internals);
180                 rte_eth_macaddr_get(client_info->slave_idx, &client_info->app_mac);
181                 ether_addr_copy(&client_info->app_mac, &arp->arp_data.arp_sha);
182                 memcpy(client_info->vlan, eth_h + 1, offset);
183                 client_info->vlan_count = offset / sizeof(struct rte_vlan_hdr);
184                 rte_spinlock_unlock(&internals->mode6.lock);
185                 return client_info->slave_idx;
186         }
187
188         /* If packet is not ARP Reply, send it on current primary port. */
189         rte_spinlock_unlock(&internals->mode6.lock);
190         rte_eth_macaddr_get(internals->current_primary_port,
191                         &arp->arp_data.arp_sha);
192         return internals->current_primary_port;
193 }
194
195 uint16_t
196 bond_mode_alb_arp_upd(struct client_data *client_info,
197                 struct rte_mbuf *pkt, struct bond_dev_private *internals)
198 {
199         struct rte_ether_hdr *eth_h;
200         struct rte_arp_hdr *arp_h;
201         uint16_t slave_idx;
202
203         rte_spinlock_lock(&internals->mode6.lock);
204         eth_h = rte_pktmbuf_mtod(pkt, struct rte_ether_hdr *);
205
206         ether_addr_copy(&client_info->app_mac, &eth_h->s_addr);
207         ether_addr_copy(&client_info->cli_mac, &eth_h->d_addr);
208         if (client_info->vlan_count > 0)
209                 eth_h->ether_type = rte_cpu_to_be_16(ETHER_TYPE_VLAN);
210         else
211                 eth_h->ether_type = rte_cpu_to_be_16(ETHER_TYPE_ARP);
212
213         arp_h = (struct rte_arp_hdr *)(
214                 (char *)eth_h + sizeof(struct rte_ether_hdr)
215                 + client_info->vlan_count * sizeof(struct rte_vlan_hdr));
216
217         memcpy(eth_h + 1, client_info->vlan,
218                         client_info->vlan_count * sizeof(struct rte_vlan_hdr));
219
220         ether_addr_copy(&client_info->app_mac, &arp_h->arp_data.arp_sha);
221         arp_h->arp_data.arp_sip = client_info->app_ip;
222         ether_addr_copy(&client_info->cli_mac, &arp_h->arp_data.arp_tha);
223         arp_h->arp_data.arp_tip = client_info->cli_ip;
224
225         arp_h->arp_hardware = rte_cpu_to_be_16(RTE_ARP_HRD_ETHER);
226         arp_h->arp_protocol = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
227         arp_h->arp_hlen = ETHER_ADDR_LEN;
228         arp_h->arp_plen = sizeof(uint32_t);
229         arp_h->arp_opcode = rte_cpu_to_be_16(RTE_ARP_OP_REPLY);
230
231         slave_idx = client_info->slave_idx;
232         rte_spinlock_unlock(&internals->mode6.lock);
233
234         return slave_idx;
235 }
236
237 void
238 bond_mode_alb_client_list_upd(struct rte_eth_dev *bond_dev)
239 {
240         struct bond_dev_private *internals = bond_dev->data->dev_private;
241         struct client_data *client_info;
242
243         int i;
244
245         /* If active slave count is 0, it's pointless to refresh alb table */
246         if (internals->active_slave_count <= 0)
247                 return;
248
249         rte_spinlock_lock(&internals->mode6.lock);
250         internals->mode6.last_slave = ALB_NULL_INDEX;
251
252         for (i = 0; i < ALB_HASH_TABLE_SIZE; i++) {
253                 client_info = &internals->mode6.client_table[i];
254                 if (client_info->in_use) {
255                         client_info->slave_idx = calculate_slave(internals);
256                         rte_eth_macaddr_get(client_info->slave_idx, &client_info->app_mac);
257                         internals->mode6.ntt = 1;
258                 }
259         }
260         rte_spinlock_unlock(&internals->mode6.lock);
261 }