xref: /dpdk/drivers/vdpa/sfc/sfc_vdpa_filter.c (revision 136d1646841ec2419dbd58bd6052c1a0c8228f0d)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2020-2021 Xilinx, Inc.
3  */
4 
5 #include <rte_errno.h>
6 #include <rte_ether.h>
7 #include <rte_kvargs.h>
8 
9 #include "efx.h"
10 #include "efx_impl.h"
11 #include "sfc_vdpa.h"
12 
13 static inline int
sfc_vdpa_get_eth_addr(const char * key __rte_unused,const char * value,void * extra_args)14 sfc_vdpa_get_eth_addr(const char *key __rte_unused,
15 		      const char *value, void *extra_args)
16 {
17 	struct rte_ether_addr *mac_addr = extra_args;
18 
19 	if (value == NULL || extra_args == NULL)
20 		return -EINVAL;
21 
22 	/* Convert string with Ethernet address to an ether_addr */
23 	rte_ether_unformat_addr(value, mac_addr);
24 
25 	return 0;
26 }
27 
28 static int
sfc_vdpa_set_mac_filter(efx_nic_t * nic,efx_filter_spec_t * spec,int qid,uint8_t * eth_addr)29 sfc_vdpa_set_mac_filter(efx_nic_t *nic, efx_filter_spec_t *spec,
30 			int qid, uint8_t *eth_addr)
31 {
32 	int rc;
33 
34 	if (nic == NULL || spec == NULL)
35 		return -1;
36 
37 	spec->efs_priority = EFX_FILTER_PRI_MANUAL;
38 	spec->efs_flags = EFX_FILTER_FLAG_RX;
39 	spec->efs_dmaq_id = qid;
40 
41 	if (eth_addr == NULL)
42 		rc = efx_filter_spec_set_mc_def(spec);
43 	else
44 		rc = efx_filter_spec_set_eth_local(spec,
45 						   EFX_FILTER_SPEC_VID_UNSPEC,
46 						   eth_addr);
47 	if (rc != 0)
48 		return rc;
49 
50 	rc = efx_filter_insert(nic, spec);
51 	if (rc != 0)
52 		return rc;
53 
54 	return rc;
55 }
56 
sfc_vdpa_filter_config(struct sfc_vdpa_ops_data * ops_data)57 int sfc_vdpa_filter_config(struct sfc_vdpa_ops_data *ops_data)
58 {
59 	int rc;
60 	int qid;
61 	efx_nic_t *nic;
62 	struct rte_ether_addr bcast_eth_addr;
63 	struct rte_ether_addr ucast_eth_addr;
64 	struct sfc_vdpa_adapter *sva = ops_data->dev_handle;
65 	efx_filter_spec_t *spec;
66 
67 	sfc_vdpa_log_init(sva, "entry");
68 
69 	nic = sva->nic;
70 
71 	sfc_vdpa_log_init(sva, "process kvarg");
72 
73 	/* skip MAC filter configuration if mac address is not provided */
74 	if (rte_kvargs_count(sva->kvargs, SFC_VDPA_MAC_ADDR) == 0) {
75 		sfc_vdpa_warn(sva,
76 			      "MAC address is not provided, skipping MAC Filter Config");
77 		return -1;
78 	}
79 
80 	rc = rte_kvargs_process(sva->kvargs, SFC_VDPA_MAC_ADDR,
81 				&sfc_vdpa_get_eth_addr,
82 				&ucast_eth_addr);
83 	if (rc < 0)
84 		return -1;
85 
86 	/* create filters on the base queue */
87 	qid = SFC_VDPA_GET_VI_INDEX(0);
88 
89 	sfc_vdpa_log_init(sva, "insert broadcast mac filter");
90 
91 	EFX_MAC_BROADCAST_ADDR_SET(bcast_eth_addr.addr_bytes);
92 	spec = &sva->filters.spec[SFC_VDPA_BCAST_MAC_FILTER];
93 
94 	rc = sfc_vdpa_set_mac_filter(nic, spec, qid,
95 				     bcast_eth_addr.addr_bytes);
96 	if (rc != 0)
97 		sfc_vdpa_err(ops_data->dev_handle,
98 			     "broadcast MAC filter insertion failed: %s",
99 			     rte_strerror(rc));
100 	else
101 		sva->filters.filter_cnt++;
102 
103 	sfc_vdpa_log_init(sva, "insert unicast mac filter");
104 	spec = &sva->filters.spec[SFC_VDPA_UCAST_MAC_FILTER];
105 
106 	rc = sfc_vdpa_set_mac_filter(nic, spec, qid,
107 				     ucast_eth_addr.addr_bytes);
108 	if (rc != 0)
109 		sfc_vdpa_err(sva, "unicast MAC filter insertion failed: %s",
110 			     rte_strerror(rc));
111 	else
112 		sva->filters.filter_cnt++;
113 
114 	sfc_vdpa_log_init(sva, "insert unknown mcast filter");
115 	spec = &sva->filters.spec[SFC_VDPA_MCAST_DST_FILTER];
116 
117 	rc = sfc_vdpa_set_mac_filter(nic, spec, qid, NULL);
118 	if (rc != 0)
119 		sfc_vdpa_err(sva,
120 			     "mcast filter insertion failed: %s",
121 			     rte_strerror(rc));
122 	else
123 		sva->filters.filter_cnt++;
124 
125 	sfc_vdpa_log_init(sva, "done");
126 
127 	return rc;
128 }
129 
sfc_vdpa_filter_remove(struct sfc_vdpa_ops_data * ops_data)130 int sfc_vdpa_filter_remove(struct sfc_vdpa_ops_data *ops_data)
131 {
132 	int i, rc = 0;
133 	struct sfc_vdpa_adapter *sva = ops_data->dev_handle;
134 	efx_nic_t *nic;
135 
136 	nic = sva->nic;
137 
138 	for (i = 0; i < sva->filters.filter_cnt; i++) {
139 		rc = efx_filter_remove(nic, &(sva->filters.spec[i]));
140 		if (rc != 0)
141 			sfc_vdpa_err(sva,
142 				     "remove HW filter failed for entry %d: %s",
143 				     i, rte_strerror(rc));
144 	}
145 
146 	sva->filters.filter_cnt = 0;
147 
148 	return rc;
149 }
150