1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
2 /*
3  * Copyright 2021 Marvell. All rights reserved.
4  */
5 
6 #include <linux/types.h>
7 #include <asm/byteorder.h>
8 #include <asm/param.h>
9 #include <linux/delay.h>
10 #include <linux/pci.h>
11 #include <linux/dma-mapping.h>
12 #include <linux/etherdevice.h>
13 #include <linux/kernel.h>
14 #include <linux/stddef.h>
15 #include <linux/errno.h>
16 
17 #include <net/tcp.h>
18 
19 #include <linux/qed/qed_nvmetcp_ip_services_if.h>
20 
21 #define QED_IP_RESOL_TIMEOUT  4
22 
qed_route_ipv4(struct sockaddr_storage * local_addr,struct sockaddr_storage * remote_addr,struct sockaddr * hardware_address,struct net_device ** ndev)23 int qed_route_ipv4(struct sockaddr_storage *local_addr,
24 		   struct sockaddr_storage *remote_addr,
25 		   struct sockaddr *hardware_address,
26 		   struct net_device **ndev)
27 {
28 	struct neighbour *neigh = NULL;
29 	__be32 *loc_ip, *rem_ip;
30 	struct rtable *rt;
31 	int rc = -ENXIO;
32 	int retry;
33 
34 	loc_ip = &((struct sockaddr_in *)local_addr)->sin_addr.s_addr;
35 	rem_ip = &((struct sockaddr_in *)remote_addr)->sin_addr.s_addr;
36 	*ndev = NULL;
37 	rt = ip_route_output(&init_net, *rem_ip, *loc_ip, 0/*tos*/, 0/*oif*/);
38 	if (IS_ERR(rt)) {
39 		pr_err("lookup route failed\n");
40 		rc = PTR_ERR(rt);
41 		goto return_err;
42 	}
43 
44 	neigh = dst_neigh_lookup(&rt->dst, rem_ip);
45 	if (!neigh) {
46 		rc = -ENOMEM;
47 		ip_rt_put(rt);
48 		goto return_err;
49 	}
50 
51 	*ndev = rt->dst.dev;
52 	ip_rt_put(rt);
53 
54 	/* If not resolved, kick-off state machine towards resolution */
55 	if (!(neigh->nud_state & NUD_VALID))
56 		neigh_event_send(neigh, NULL);
57 
58 	/* query neighbor until resolved or timeout */
59 	retry = QED_IP_RESOL_TIMEOUT;
60 	while (!(neigh->nud_state & NUD_VALID) && retry > 0) {
61 		msleep(1000);
62 		retry--;
63 	}
64 
65 	if (neigh->nud_state & NUD_VALID) {
66 		/* copy resolved MAC address */
67 		neigh_ha_snapshot(hardware_address->sa_data, neigh, *ndev);
68 		hardware_address->sa_family = (*ndev)->type;
69 		rc = 0;
70 	}
71 
72 	neigh_release(neigh);
73 	if (!(*loc_ip)) {
74 		*loc_ip = inet_select_addr(*ndev, *rem_ip, RT_SCOPE_UNIVERSE);
75 		local_addr->ss_family = AF_INET;
76 	}
77 
78 return_err:
79 
80 	return rc;
81 }
82 EXPORT_SYMBOL(qed_route_ipv4);
83 
qed_route_ipv6(struct sockaddr_storage * local_addr,struct sockaddr_storage * remote_addr,struct sockaddr * hardware_address,struct net_device ** ndev)84 int qed_route_ipv6(struct sockaddr_storage *local_addr,
85 		   struct sockaddr_storage *remote_addr,
86 		   struct sockaddr *hardware_address,
87 		   struct net_device **ndev)
88 {
89 	struct neighbour *neigh = NULL;
90 	struct dst_entry *dst;
91 	struct flowi6 fl6;
92 	int rc = -ENXIO;
93 	int retry;
94 
95 	memset(&fl6, 0, sizeof(fl6));
96 	fl6.saddr = ((struct sockaddr_in6 *)local_addr)->sin6_addr;
97 	fl6.daddr = ((struct sockaddr_in6 *)remote_addr)->sin6_addr;
98 	dst = ip6_route_output(&init_net, NULL, &fl6);
99 	if (!dst || dst->error) {
100 		if (dst) {
101 			dst_release(dst);
102 			pr_err("lookup route failed %d\n", dst->error);
103 		}
104 
105 		goto out;
106 	}
107 
108 	neigh = dst_neigh_lookup(dst, &fl6.daddr);
109 	if (neigh) {
110 		*ndev = ip6_dst_idev(dst)->dev;
111 
112 		/* If not resolved, kick-off state machine towards resolution */
113 		if (!(neigh->nud_state & NUD_VALID))
114 			neigh_event_send(neigh, NULL);
115 
116 		/* query neighbor until resolved or timeout */
117 		retry = QED_IP_RESOL_TIMEOUT;
118 		while (!(neigh->nud_state & NUD_VALID) && retry > 0) {
119 			msleep(1000);
120 			retry--;
121 		}
122 
123 		if (neigh->nud_state & NUD_VALID) {
124 			neigh_ha_snapshot((u8 *)hardware_address->sa_data,
125 					  neigh, *ndev);
126 			hardware_address->sa_family = (*ndev)->type;
127 			rc = 0;
128 		}
129 
130 		neigh_release(neigh);
131 
132 		if (ipv6_addr_any(&fl6.saddr)) {
133 			if (ipv6_dev_get_saddr(dev_net(*ndev), *ndev,
134 					       &fl6.daddr, 0, &fl6.saddr)) {
135 				pr_err("Unable to find source IP address\n");
136 				goto out;
137 			}
138 
139 			local_addr->ss_family = AF_INET6;
140 			((struct sockaddr_in6 *)local_addr)->sin6_addr =
141 								fl6.saddr;
142 		}
143 	}
144 
145 	dst_release(dst);
146 
147 out:
148 
149 	return rc;
150 }
151 EXPORT_SYMBOL(qed_route_ipv6);
152 
qed_vlan_get_ndev(struct net_device ** ndev,u16 * vlan_id)153 void qed_vlan_get_ndev(struct net_device **ndev, u16 *vlan_id)
154 {
155 	if (is_vlan_dev(*ndev)) {
156 		*vlan_id = vlan_dev_vlan_id(*ndev);
157 		*ndev = vlan_dev_real_dev(*ndev);
158 	}
159 }
160 EXPORT_SYMBOL(qed_vlan_get_ndev);
161 
qed_validate_ndev(struct net_device * ndev)162 struct pci_dev *qed_validate_ndev(struct net_device *ndev)
163 {
164 	struct pci_dev *pdev = NULL;
165 	struct net_device *upper;
166 
167 	for_each_pci_dev(pdev) {
168 		if (pdev && pdev->driver &&
169 		    !strcmp(pdev->driver->name, "qede")) {
170 			upper = pci_get_drvdata(pdev);
171 			if (upper->ifindex == ndev->ifindex)
172 				return pdev;
173 		}
174 	}
175 
176 	return NULL;
177 }
178 EXPORT_SYMBOL(qed_validate_ndev);
179 
qed_get_in_port(struct sockaddr_storage * sa)180 __be16 qed_get_in_port(struct sockaddr_storage *sa)
181 {
182 	return sa->ss_family == AF_INET
183 		? ((struct sockaddr_in *)sa)->sin_port
184 		: ((struct sockaddr_in6 *)sa)->sin6_port;
185 }
186 EXPORT_SYMBOL(qed_get_in_port);
187 
qed_fetch_tcp_port(struct sockaddr_storage local_ip_addr,struct socket ** sock,u16 * port)188 int qed_fetch_tcp_port(struct sockaddr_storage local_ip_addr,
189 		       struct socket **sock, u16 *port)
190 {
191 	struct sockaddr_storage sa;
192 	int rc = 0;
193 
194 	rc = sock_create(local_ip_addr.ss_family, SOCK_STREAM, IPPROTO_TCP,
195 			 sock);
196 	if (rc) {
197 		pr_warn("failed to create socket: %d\n", rc);
198 		goto err;
199 	}
200 
201 	(*sock)->sk->sk_allocation = GFP_KERNEL;
202 	sk_set_memalloc((*sock)->sk);
203 
204 	rc = kernel_bind(*sock, (struct sockaddr *)&local_ip_addr,
205 			 sizeof(local_ip_addr));
206 
207 	if (rc) {
208 		pr_warn("failed to bind socket: %d\n", rc);
209 		goto err_sock;
210 	}
211 
212 	rc = kernel_getsockname(*sock, (struct sockaddr *)&sa);
213 	if (rc < 0) {
214 		pr_warn("getsockname() failed: %d\n", rc);
215 		goto err_sock;
216 	}
217 
218 	*port = ntohs(qed_get_in_port(&sa));
219 
220 	return 0;
221 
222 err_sock:
223 	sock_release(*sock);
224 	sock = NULL;
225 err:
226 
227 	return rc;
228 }
229 EXPORT_SYMBOL(qed_fetch_tcp_port);
230 
qed_return_tcp_port(struct socket * sock)231 void qed_return_tcp_port(struct socket *sock)
232 {
233 	if (sock && sock->sk) {
234 		tcp_set_state(sock->sk, TCP_CLOSE);
235 		sock_release(sock);
236 	}
237 }
238 EXPORT_SYMBOL(qed_return_tcp_port);
239