xref: /dpdk/drivers/net/failsafe/failsafe_ether.c (revision a0194d828100ecf549763d1a80f08cc61275840f)
1ebea83f8SGaetan Rivet /*-
2ebea83f8SGaetan Rivet  *   BSD LICENSE
3ebea83f8SGaetan Rivet  *
4ebea83f8SGaetan Rivet  *   Copyright 2017 6WIND S.A.
5ebea83f8SGaetan Rivet  *   Copyright 2017 Mellanox.
6ebea83f8SGaetan Rivet  *
7ebea83f8SGaetan Rivet  *   Redistribution and use in source and binary forms, with or without
8ebea83f8SGaetan Rivet  *   modification, are permitted provided that the following conditions
9ebea83f8SGaetan Rivet  *   are met:
10ebea83f8SGaetan Rivet  *
11ebea83f8SGaetan Rivet  *     * Redistributions of source code must retain the above copyright
12ebea83f8SGaetan Rivet  *       notice, this list of conditions and the following disclaimer.
13ebea83f8SGaetan Rivet  *     * Redistributions in binary form must reproduce the above copyright
14ebea83f8SGaetan Rivet  *       notice, this list of conditions and the following disclaimer in
15ebea83f8SGaetan Rivet  *       the documentation and/or other materials provided with the
16ebea83f8SGaetan Rivet  *       distribution.
17ebea83f8SGaetan Rivet  *     * Neither the name of 6WIND S.A. nor the names of its
18ebea83f8SGaetan Rivet  *       contributors may be used to endorse or promote products derived
19ebea83f8SGaetan Rivet  *       from this software without specific prior written permission.
20ebea83f8SGaetan Rivet  *
21ebea83f8SGaetan Rivet  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22ebea83f8SGaetan Rivet  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23ebea83f8SGaetan Rivet  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24ebea83f8SGaetan Rivet  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25ebea83f8SGaetan Rivet  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26ebea83f8SGaetan Rivet  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27ebea83f8SGaetan Rivet  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28ebea83f8SGaetan Rivet  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29ebea83f8SGaetan Rivet  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30ebea83f8SGaetan Rivet  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31ebea83f8SGaetan Rivet  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32ebea83f8SGaetan Rivet  */
33ebea83f8SGaetan Rivet 
34ebea83f8SGaetan Rivet #include <unistd.h>
35ebea83f8SGaetan Rivet 
36ebea83f8SGaetan Rivet #include "failsafe_private.h"
37ebea83f8SGaetan Rivet 
38ebea83f8SGaetan Rivet static int
39ebea83f8SGaetan Rivet fs_eth_dev_conf_apply(struct rte_eth_dev *dev,
40ebea83f8SGaetan Rivet 		struct sub_device *sdev)
41ebea83f8SGaetan Rivet {
42ebea83f8SGaetan Rivet 	struct rte_eth_dev *edev;
43ebea83f8SGaetan Rivet 	struct rte_vlan_filter_conf *vfc1;
44ebea83f8SGaetan Rivet 	struct rte_vlan_filter_conf *vfc2;
45ebea83f8SGaetan Rivet 	uint32_t i;
46ebea83f8SGaetan Rivet 	int ret;
47ebea83f8SGaetan Rivet 
48ebea83f8SGaetan Rivet 	edev = ETH(sdev);
49ebea83f8SGaetan Rivet 	/* RX queue setup */
50ebea83f8SGaetan Rivet 	for (i = 0; i < dev->data->nb_rx_queues; i++) {
51ebea83f8SGaetan Rivet 		struct rxq *rxq;
52ebea83f8SGaetan Rivet 
53ebea83f8SGaetan Rivet 		rxq = dev->data->rx_queues[i];
54ebea83f8SGaetan Rivet 		ret = rte_eth_rx_queue_setup(PORT_ID(sdev), i,
55ebea83f8SGaetan Rivet 				rxq->info.nb_desc, rxq->socket_id,
56ebea83f8SGaetan Rivet 				&rxq->info.conf, rxq->info.mp);
57ebea83f8SGaetan Rivet 		if (ret) {
58ebea83f8SGaetan Rivet 			ERROR("rx_queue_setup failed");
59ebea83f8SGaetan Rivet 			return ret;
60ebea83f8SGaetan Rivet 		}
61ebea83f8SGaetan Rivet 	}
62ebea83f8SGaetan Rivet 	/* TX queue setup */
63ebea83f8SGaetan Rivet 	for (i = 0; i < dev->data->nb_tx_queues; i++) {
64ebea83f8SGaetan Rivet 		struct txq *txq;
65ebea83f8SGaetan Rivet 
66ebea83f8SGaetan Rivet 		txq = dev->data->tx_queues[i];
67ebea83f8SGaetan Rivet 		ret = rte_eth_tx_queue_setup(PORT_ID(sdev), i,
68ebea83f8SGaetan Rivet 				txq->info.nb_desc, txq->socket_id,
69ebea83f8SGaetan Rivet 				&txq->info.conf);
70ebea83f8SGaetan Rivet 		if (ret) {
71ebea83f8SGaetan Rivet 			ERROR("tx_queue_setup failed");
72ebea83f8SGaetan Rivet 			return ret;
73ebea83f8SGaetan Rivet 		}
74ebea83f8SGaetan Rivet 	}
75ebea83f8SGaetan Rivet 	/* dev_link.link_status */
76ebea83f8SGaetan Rivet 	if (dev->data->dev_link.link_status !=
77ebea83f8SGaetan Rivet 	    edev->data->dev_link.link_status) {
78ebea83f8SGaetan Rivet 		DEBUG("Configuring link_status");
79ebea83f8SGaetan Rivet 		if (dev->data->dev_link.link_status)
80ebea83f8SGaetan Rivet 			ret = rte_eth_dev_set_link_up(PORT_ID(sdev));
81ebea83f8SGaetan Rivet 		else
82ebea83f8SGaetan Rivet 			ret = rte_eth_dev_set_link_down(PORT_ID(sdev));
83ebea83f8SGaetan Rivet 		if (ret) {
84ebea83f8SGaetan Rivet 			ERROR("Failed to apply link_status");
85ebea83f8SGaetan Rivet 			return ret;
86ebea83f8SGaetan Rivet 		}
87ebea83f8SGaetan Rivet 	} else {
88ebea83f8SGaetan Rivet 		DEBUG("link_status already set");
89ebea83f8SGaetan Rivet 	}
90ebea83f8SGaetan Rivet 	/* promiscuous */
91ebea83f8SGaetan Rivet 	if (dev->data->promiscuous != edev->data->promiscuous) {
92ebea83f8SGaetan Rivet 		DEBUG("Configuring promiscuous");
93ebea83f8SGaetan Rivet 		if (dev->data->promiscuous)
94ebea83f8SGaetan Rivet 			rte_eth_promiscuous_enable(PORT_ID(sdev));
95ebea83f8SGaetan Rivet 		else
96ebea83f8SGaetan Rivet 			rte_eth_promiscuous_disable(PORT_ID(sdev));
97ebea83f8SGaetan Rivet 	} else {
98ebea83f8SGaetan Rivet 		DEBUG("promiscuous already set");
99ebea83f8SGaetan Rivet 	}
100ebea83f8SGaetan Rivet 	/* all_multicast */
101ebea83f8SGaetan Rivet 	if (dev->data->all_multicast != edev->data->all_multicast) {
102ebea83f8SGaetan Rivet 		DEBUG("Configuring all_multicast");
103ebea83f8SGaetan Rivet 		if (dev->data->all_multicast)
104ebea83f8SGaetan Rivet 			rte_eth_allmulticast_enable(PORT_ID(sdev));
105ebea83f8SGaetan Rivet 		else
106ebea83f8SGaetan Rivet 			rte_eth_allmulticast_disable(PORT_ID(sdev));
107ebea83f8SGaetan Rivet 	} else {
108ebea83f8SGaetan Rivet 		DEBUG("all_multicast already set");
109ebea83f8SGaetan Rivet 	}
110ebea83f8SGaetan Rivet 	/* MTU */
111ebea83f8SGaetan Rivet 	if (dev->data->mtu != edev->data->mtu) {
112ebea83f8SGaetan Rivet 		DEBUG("Configuring MTU");
113ebea83f8SGaetan Rivet 		ret = rte_eth_dev_set_mtu(PORT_ID(sdev), dev->data->mtu);
114ebea83f8SGaetan Rivet 		if (ret) {
115ebea83f8SGaetan Rivet 			ERROR("Failed to apply MTU");
116ebea83f8SGaetan Rivet 			return ret;
117ebea83f8SGaetan Rivet 		}
118ebea83f8SGaetan Rivet 	} else {
119ebea83f8SGaetan Rivet 		DEBUG("MTU already set");
120ebea83f8SGaetan Rivet 	}
121ebea83f8SGaetan Rivet 	/* default MAC */
122ebea83f8SGaetan Rivet 	DEBUG("Configuring default MAC address");
123ebea83f8SGaetan Rivet 	ret = rte_eth_dev_default_mac_addr_set(PORT_ID(sdev),
124ebea83f8SGaetan Rivet 			&dev->data->mac_addrs[0]);
125ebea83f8SGaetan Rivet 	if (ret) {
126ebea83f8SGaetan Rivet 		ERROR("Setting default MAC address failed");
127ebea83f8SGaetan Rivet 		return ret;
128ebea83f8SGaetan Rivet 	}
129ebea83f8SGaetan Rivet 	/* additional MAC */
130ebea83f8SGaetan Rivet 	if (PRIV(dev)->nb_mac_addr > 1)
131ebea83f8SGaetan Rivet 		DEBUG("Configure additional MAC address%s",
132ebea83f8SGaetan Rivet 			(PRIV(dev)->nb_mac_addr > 2 ? "es" : ""));
133ebea83f8SGaetan Rivet 	for (i = 1; i < PRIV(dev)->nb_mac_addr; i++) {
134ebea83f8SGaetan Rivet 		struct ether_addr *ea;
135ebea83f8SGaetan Rivet 
136ebea83f8SGaetan Rivet 		ea = &dev->data->mac_addrs[i];
137ebea83f8SGaetan Rivet 		ret = rte_eth_dev_mac_addr_add(PORT_ID(sdev), ea,
138ebea83f8SGaetan Rivet 				PRIV(dev)->mac_addr_pool[i]);
139ebea83f8SGaetan Rivet 		if (ret) {
140ebea83f8SGaetan Rivet 			char ea_fmt[ETHER_ADDR_FMT_SIZE];
141ebea83f8SGaetan Rivet 
142ebea83f8SGaetan Rivet 			ether_format_addr(ea_fmt, ETHER_ADDR_FMT_SIZE, ea);
143ebea83f8SGaetan Rivet 			ERROR("Adding MAC address %s failed", ea_fmt);
144ebea83f8SGaetan Rivet 		}
145ebea83f8SGaetan Rivet 	}
146ebea83f8SGaetan Rivet 	/* VLAN filter */
147ebea83f8SGaetan Rivet 	vfc1 = &dev->data->vlan_filter_conf;
148ebea83f8SGaetan Rivet 	vfc2 = &edev->data->vlan_filter_conf;
149ebea83f8SGaetan Rivet 	if (memcmp(vfc1, vfc2, sizeof(struct rte_vlan_filter_conf))) {
150ebea83f8SGaetan Rivet 		uint64_t vbit;
151ebea83f8SGaetan Rivet 		uint64_t ids;
152ebea83f8SGaetan Rivet 		size_t i;
153ebea83f8SGaetan Rivet 		uint16_t vlan_id;
154ebea83f8SGaetan Rivet 
155ebea83f8SGaetan Rivet 		DEBUG("Configuring VLAN filter");
156ebea83f8SGaetan Rivet 		for (i = 0; i < RTE_DIM(vfc1->ids); i++) {
157ebea83f8SGaetan Rivet 			if (vfc1->ids[i] == 0)
158ebea83f8SGaetan Rivet 				continue;
159ebea83f8SGaetan Rivet 			ids = vfc1->ids[i];
160ebea83f8SGaetan Rivet 			while (ids) {
161ebea83f8SGaetan Rivet 				vlan_id = 64 * i;
162ebea83f8SGaetan Rivet 				/* count trailing zeroes */
163ebea83f8SGaetan Rivet 				vbit = ~ids & (ids - 1);
164ebea83f8SGaetan Rivet 				/* clear least significant bit set */
165ebea83f8SGaetan Rivet 				ids ^= (ids ^ (ids - 1)) ^ vbit;
166ebea83f8SGaetan Rivet 				for (; vbit; vlan_id++)
167ebea83f8SGaetan Rivet 					vbit >>= 1;
168ebea83f8SGaetan Rivet 				ret = rte_eth_dev_vlan_filter(
169ebea83f8SGaetan Rivet 					PORT_ID(sdev), vlan_id, 1);
170ebea83f8SGaetan Rivet 				if (ret) {
171ebea83f8SGaetan Rivet 					ERROR("Failed to apply VLAN filter %hu",
172ebea83f8SGaetan Rivet 						vlan_id);
173ebea83f8SGaetan Rivet 					return ret;
174ebea83f8SGaetan Rivet 				}
175ebea83f8SGaetan Rivet 			}
176ebea83f8SGaetan Rivet 		}
177ebea83f8SGaetan Rivet 	} else {
178ebea83f8SGaetan Rivet 		DEBUG("VLAN filter already set");
179ebea83f8SGaetan Rivet 	}
180ebea83f8SGaetan Rivet 	return 0;
181ebea83f8SGaetan Rivet }
182ebea83f8SGaetan Rivet 
183ebea83f8SGaetan Rivet int
184ebea83f8SGaetan Rivet failsafe_eth_dev_state_sync(struct rte_eth_dev *dev)
185ebea83f8SGaetan Rivet {
186ebea83f8SGaetan Rivet 	struct sub_device *sdev;
187ebea83f8SGaetan Rivet 	uint32_t inactive;
188ebea83f8SGaetan Rivet 	int ret;
189ebea83f8SGaetan Rivet 	uint8_t i;
190ebea83f8SGaetan Rivet 
191*a0194d82SGaetan Rivet 	if (PRIV(dev)->state < DEV_PARSED)
192*a0194d82SGaetan Rivet 		return 0;
193*a0194d82SGaetan Rivet 
194*a0194d82SGaetan Rivet 	ret = failsafe_args_parse_subs(dev);
195*a0194d82SGaetan Rivet 	if (ret)
196*a0194d82SGaetan Rivet 		return ret;
197*a0194d82SGaetan Rivet 
198ebea83f8SGaetan Rivet 	if (PRIV(dev)->state < DEV_PROBED)
199ebea83f8SGaetan Rivet 		return 0;
200ebea83f8SGaetan Rivet 	ret = failsafe_eal_init(dev);
201ebea83f8SGaetan Rivet 	if (ret)
202ebea83f8SGaetan Rivet 		return ret;
203ebea83f8SGaetan Rivet 	if (PRIV(dev)->state < DEV_ACTIVE)
204ebea83f8SGaetan Rivet 		return 0;
205ebea83f8SGaetan Rivet 	inactive = 0;
206ebea83f8SGaetan Rivet 	FOREACH_SUBDEV(sdev, i, dev)
207ebea83f8SGaetan Rivet 		if (sdev->state == DEV_PROBED)
208ebea83f8SGaetan Rivet 			inactive |= UINT32_C(1) << i;
209ebea83f8SGaetan Rivet 	ret = dev->dev_ops->dev_configure(dev);
210ebea83f8SGaetan Rivet 	if (ret)
211ebea83f8SGaetan Rivet 		return ret;
212ebea83f8SGaetan Rivet 	FOREACH_SUBDEV(sdev, i, dev) {
213ebea83f8SGaetan Rivet 		if (inactive & (UINT32_C(1) << i)) {
214ebea83f8SGaetan Rivet 			ret = fs_eth_dev_conf_apply(dev, sdev);
215ebea83f8SGaetan Rivet 			if (ret) {
216ebea83f8SGaetan Rivet 				ERROR("Could not apply configuration to sub_device %d",
217ebea83f8SGaetan Rivet 				      i);
218ebea83f8SGaetan Rivet 				/* TODO: disable device */
219ebea83f8SGaetan Rivet 				return ret;
220ebea83f8SGaetan Rivet 			}
221ebea83f8SGaetan Rivet 		}
222ebea83f8SGaetan Rivet 	}
223ebea83f8SGaetan Rivet 	/*
224ebea83f8SGaetan Rivet 	 * If new devices have been configured, check if
225ebea83f8SGaetan Rivet 	 * the link state has changed.
226ebea83f8SGaetan Rivet 	 */
227ebea83f8SGaetan Rivet 	if (inactive)
228ebea83f8SGaetan Rivet 		dev->dev_ops->link_update(dev, 1);
229ebea83f8SGaetan Rivet 	if (PRIV(dev)->state < DEV_STARTED)
230ebea83f8SGaetan Rivet 		return 0;
231ebea83f8SGaetan Rivet 	ret = dev->dev_ops->dev_start(dev);
232ebea83f8SGaetan Rivet 	if (ret)
233ebea83f8SGaetan Rivet 		return ret;
234ebea83f8SGaetan Rivet 	return 0;
235ebea83f8SGaetan Rivet }
236