blob: bab77ca6e820e3ec9124fd267e1005173ee0ff8a [file] [log] [blame]
Shad Ansari2f7f9be2017-06-07 13:34:53 -07001/*
2<:copyright-BRCM:2016:DUAL/GPL:standard
3
4 Broadcom Proprietary and Confidential.(c) 2016 Broadcom
5 All Rights Reserved
6
7Unless you and Broadcom execute a separate written software license
8agreement governing use of this software, this software is licensed
9to you under the terms of the GNU General Public License version 2
10(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
11with the following added to such license:
12
13 As a special exception, the copyright holders of this software give
14 you permission to link this software with independent modules, and
15 to copy and distribute the resulting executable under terms of your
16 choice, provided that you also meet, for each linked independent
17 module, the terms and conditions of the license of that module.
18 An independent module is a module which is not derived from this
19 software. The special exception does not apply to any modifications
20 of the software.
21
22Not withstanding the above, under no circumstances may you combine
23this software in any way with any other Broadcom software provided
24under a license other than the GPL, without Broadcom's express prior
25written consent.
26
27:>
28 */
29
30/*
31 * bcmtr_inband.c - In-band transport driver
32 */
33#include <bcmos_system.h>
34#include <bcmtr_inband.h>
35#include <sys/types.h>
36#include <sys/socket.h>
37
38typedef struct device_info
39{
40 bcmos_ipv4_address remote_ip;
41 uint16_t remote_port;
42 uint8_t channel;
43 int tr_udp_sock;
44} device_info;
45
46static device_info dev_info[BCMTR_MAX_OLTS];
47
48#define DEBUG_ONLY 0
49
50/** Initialize in-band transport driver
51 * \returns: 0 in case of success or error code < 0
52 */
53bcmos_errno bcmtr_ib_init(void)
54{
55 return BCM_ERR_OK;
56}
57
58/** Cleanup in-band transport driver
59 * \returns: 0 in case of success or error code < 0
60 */
61void bcmtr_ib_exit(void)
62{
63 int i;
64
65 for (i=0; i<BCMTR_MAX_OLTS; i++)
66 {
67 bcmtr_ib_disconnect(i);
68 }
69}
70
71/* Receive packet */
72static bcmos_errno _bcmtr_ib_rx(uint32_t device, int s, bcmos_buf **buf, uint8_t *ch)
73{
74 struct sockaddr_in sa;
75#if 0
76 struct iovec iov = {.iov_len = BCMTR_MAX_MTU_SIZE};
77 struct msghdr msg = {
78 .msg_iov = &iov, .msg_iovlen = 1,
79 .msg_name = &sa, .msg_namelen = sizeof(sa)
80 };
81#endif
82 bcmos_buf *b;
83 ssize_t len;
84
85 b = bcmos_buf_alloc(BCMTR_MAX_MTU_SIZE);
86 if (!b)
87 {
88 bcmos_printf("%s: Failed to allocate buffer\n", __FUNCTION__);
89 return BCM_ERR_NOMEM;
90 }
91#if 0
92 iov.iov_base = bcmos_buf_data(b);
93#endif
94 memset(&sa, 0, sizeof(sa));
95 len = recv(s, bcmos_buf_data(b), BCMTR_MAX_MTU_SIZE, 0);
96 if (len <= 0)
97 {
98 bcmos_printf("%s: recvmsg() --> %d\n", __FUNCTION__, len);
99 bcmos_buf_free(b);
100 return BCM_ERR_COMM_FAIL;
101 }
102
103 *ch = dev_info[device].channel;
104 dev_info[device].channel = 0;
105 bcmos_buf_length_set(b, (int)len);
106 *buf = b;
107
108#if DEBUG_ONLY
109 bcmos_printf("\nReceived to %d bytes from channel %d/%d port", len, *ch, sa.sin_port);
110
111 {
112 int ii = 0;
113 unsigned char *c = bcmos_buf_data(b);
114 int size = (int)len;
115
116 for (ii=0; ii<size; ii++)
117 {
118 if (0==(ii%16)) bcmos_printf("\n");
119 if (0==(ii%8)) bcmos_printf(" ");
120 bcmos_printf(" %02x", *c);
121 c++;
122 }
123 bcmos_printf("\n");
124 }
125#endif
126
127 return BCM_ERR_OK;
128}
129
130/** Connect to maple device */
131bcmos_errno bcmtr_ib_connect(uint8_t device, bcmos_ipv4_address ip_address, uint16_t udp_port)
132{
133 int r = 0;
134 int s = 0;
135 struct sockaddr_in sa;
136
137 /*Check for valid device*/
138 BUG_ON((unsigned)device >= BCMTR_MAX_OLTS);
139
140 if (dev_info[device].tr_udp_sock)
141 return BCM_ERR_ALREADY;
142
143 dev_info[device].remote_ip = ip_address;
144 dev_info[device].remote_port = udp_port;
145
146 /*check that ip address and port have been initialized*/
147 if(dev_info[device].remote_port == 0 || dev_info[device].remote_ip.u32 == 0)
148 {
149 bcmos_printf("%s: IP address and port not initialized. Error %d\n", __FUNCTION__, r);
150 return BCM_ERR_RANGE;
151 }
152
153 /* Create socket */
154 s = socket(AF_INET, SOCK_DGRAM, 0);
155 if (!s)
156 {
157 bcmos_printf("%s: Failed to create socket. Error %d\n", __FUNCTION__, s);
158 return BCM_ERR_COMM_FAIL;
159 }
160
161 /* Connect to remote */
162 memset(&sa, 0, sizeof(sa));
163 sa.sin_family = AF_INET;
164 sa.sin_port = (in_port_t)htons(dev_info[device].remote_port);
165 sa.sin_addr.s_addr = (in_addr_t)htonl(dev_info[device].remote_ip.u32);
166 r = connect(s, (struct sockaddr*)&sa, sizeof(sa));
167 if (r)
168 {
169 bcmos_printf("%s: Failed to connect socket. Error %d\n", __FUNCTION__, r);
170 close(s);
171 return BCM_ERR_COMM_FAIL;
172 }
173
174 {
175 socklen_t slen;
176 if (getsockname(s, (struct sockaddr *)&sa, &slen) < 0)
177 {
178 bcmos_printf("%s: Connected socket invalid. Error %d\n", __FUNCTION__, r);
179 close(s);
180 return BCM_ERR_COMM_FAIL;
181 }
182
183 bcmos_printf("%s: device %d: socket (port %d) connected to %d.%d.%d.%d:%d\n",
184 __FUNCTION__, device, ntohs((uint16_t)sa.sin_port),
185 (int)(dev_info[device].remote_ip.u32 >> 24), (int)((dev_info[device].remote_ip.u32 >> 16) & 0xff),
186 (int)((dev_info[device].remote_ip.u32 >> 8) & 0xff), (int)(dev_info[device].remote_ip.u32 & 0xff),
187 (int)dev_info[device].remote_port);
188 }
189
190 dev_info[device].tr_udp_sock = s;
191
192 return BCM_ERR_OK;
193}
194
195/** Disconnect. All buffers are released
196 * \param[in] device Maple device index
197 * \returns: 0 in case of success or error code < 0
198 */
199bcmos_errno bcmtr_ib_disconnect(uint8_t device)
200{
201 BUG_ON((unsigned)device >= BCMTR_MAX_OLTS);
202
203 bcmos_printf("%s: disconnecting %d..", __FUNCTION__, device);
204 if (dev_info[device].tr_udp_sock)
205 {
206 int s = dev_info[device].tr_udp_sock;
207 dev_info[device].tr_udp_sock = 0;
208 close(s);
209 }
210 bcmos_printf("done\n");
211 return BCM_ERR_OK;
212}
213
214/** Send packet to device via in-band interface
215 * \param[in] device Mapole device index
216 * \param[in] channel Logical channel
217 * \param[in] buf Buffer to be transmitted
218 * \returns: 0 in case of success or error code < 0
219 */
220bcmos_errno bcmtr_ib_send(uint8_t device, uint8_t channel, bcmos_buf *buf)
221{
222 int buflen = bcmos_buf_length(buf);
223 struct iovec iov = { .iov_base = bcmos_buf_data(buf), .iov_len = buflen };
224 struct msghdr msg = {
225 .msg_iov = &iov, .msg_iovlen = 1, .msg_flags=MSG_DONTWAIT,
226 .msg_name = NULL, .msg_namelen = 0
227 };
228 ssize_t len;
229
230 dev_info[device].channel = channel;
231
232 len = sendmsg(dev_info[device].tr_udp_sock, &msg, 0);
233 if ((int)len < buflen)
234 {
235 bcmos_printf("%s: sendmsg(%u) --> %d\n", __FUNCTION__, buflen, len);
236 bcmos_buf_free(buf);
237 return BCM_ERR_NOT_CONNECTED;
238 }
239
240#if 1
241 {
242 int ii = 0;
243 unsigned char *c = bcmos_buf_data(buf);
244 struct sockaddr_in sa;
245 socklen_t slen;
246
247 for (ii=0; ii<(int)len; ii++)
248 {
249 if (0==(ii%16)) bcmos_printf("\n");
250 if (0==(ii%8)) bcmos_printf(" ");
251 bcmos_printf(" %02x", *c);
252 c++;
253 }
254
255 if (getsockname(dev_info[device].tr_udp_sock, (struct sockaddr *)&sa, &slen) < 0)
256 {
257 bcmos_printf("%s: Connected socket invalid\n", __FUNCTION__);
258 return BCM_ERR_COMM_FAIL;
259 }
260 bcmos_printf("\nSent %d bytes to channel %d from port %d\t", len, channel, sa.sin_port);
261 }
262#endif
263
264 return BCM_ERR_OK;
265}
266
267/* Receive packet from device */
268bcmos_errno bcmtr_ib_receive(uint32_t device, uint8_t *channel, bcmos_buf **buf)
269{
270 if (device >= BCMTR_MAX_OLTS || ! dev_info[device].tr_udp_sock)
271 {
272 return BCM_ERR_PARM;
273 }
274
275 return _bcmtr_ib_rx(device, dev_info[device].tr_udp_sock, buf, channel);
276}