blob: 83d58e20e54f5559c2e5bf6ed8a0ffe0b95f2e48 [file] [log] [blame]
developeraab9e962022-04-07 12:49:36 +08001 /*
2* If not stated otherwise in this file or this component's LICENSE file the
3* following copyright and licenses apply:
4*
5* Copyright 2019 RDK Management
6*
7* Licensed under the Apache License, Version 2.0 (the "License");
8* you may not use this file except in compliance with the License.
9* You may obtain a copy of the License at
10*
11* http://www.apache.org/licenses/LICENSE-2.0
12*
13* Unless required by applicable law or agreed to in writing, software
14* distributed under the License is distributed on an "AS IS" BASIS,
15* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16* See the License for the specific language governing permissions and
17* limitations under the License.
18*/
19
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23#include <unistd.h>
24#include <sys/ioctl.h> /* ioctl() */
25#include <sys/socket.h> /* socket() */
26#include <arpa/inet.h>
developeraab9e962022-04-07 12:49:36 +080027#include <linux/if.h> /* struct ifreq */
developer2b1a9142022-04-14 18:10:59 +080028#include <stdbool.h>
developeraab9e962022-04-07 12:49:36 +080029
30#include "ccsp_hal_ethsw.h"
31
32
33/**********************************************************************
34 DEFINITIONS
35**********************************************************************/
36
37#define CcspHalEthSwTrace(msg) printf("%s - ", __FUNCTION__); printf msg;
38#define MAX_BUF_SIZE 1024
39#define MACADDRESS_SIZE 6
40#define LM_ARP_ENTRY_FORMAT "%63s %63s %63s %63s %17s %63s"
41
developer2b1a9142022-04-14 18:10:59 +080042#define ETH_WAN_INTERFACE "erouter0"
43#define ETH_WAN_IFNAME "eth2"
44#if defined(FEATURE_RDKB_WAN_MANAGER)
45static pthread_t ethsw_tid;
46static int hal_init_done = 0;
47appCallBack ethWanCallbacks;
48#define ETH_INITIALIZE "/tmp/ethagent_initialized"
49void *ethsw_thread_main(void *context __attribute__((unused)));
50#endif
developeraab9e962022-04-07 12:49:36 +080051
52#define ETHSWITCHTOOL "ethtool"
developer84fcc022022-04-15 16:25:57 +080053#define MIITOOL "mii_mgr_cl45"
54#define WANLINKUP "0x796D"
developerc63ec4a2022-12-26 16:08:58 +080055#define MAX_LAN_PORT 6
developeraab9e962022-04-07 12:49:36 +080056/**********************************************************************
57 MAIN ROUTINES
58**********************************************************************/
59
60CCSP_HAL_ETHSW_ADMIN_STATUS admin_status;
61
62int is_interface_exists(const char *fname)
63{
64 FILE *file;
65 if ((file = fopen(fname, "r")))
66 {
67 fclose(file);
68 return 1;
69 }
70 return 0;
71}
72
73int is_interface_link(const char *fname)
74{
75 FILE *file;
76 if ((file = fopen(fname, "r")))
77 {
78 char buf[32] = {0};
79 fgets(buf,sizeof(buf),file);
80 fclose(file);
developerc63ec4a2022-12-26 16:08:58 +080081 if(strtol(buf, NULL, 10))
developeraab9e962022-04-07 12:49:36 +080082 return 1;
83 }
84 return 0;
85}
86/* CcspHalEthSwInit : */
87/**
88* @description Do what needed to intialize the Eth hal.
89* @param None
90*
91* @return The status of the operation.
92* @retval RETURN_OK if successful.
93* @retval RETURN_ERR if any error is detected
94*
95* @execution Synchronous.
96* @sideeffect None.
97
98*
99* @note This function must not suspend and must not invoke any blocking system
100* calls. It should probably just send a message to a driver event handler task.
101*
102*/
103INT
104CcspHalEthSwInit
105 (
106 void
107 )
108{
developer2b1a9142022-04-14 18:10:59 +0800109#if defined(FEATURE_RDKB_WAN_MANAGER)
110 int rc;
111
112 if (hal_init_done) {
113 return RETURN_OK;
114 }
115
116 // Create thread to handle async events and callbacks.
117 rc = pthread_create(&ethsw_tid, NULL, ethsw_thread_main, NULL);
118 if (rc != 0) {
119 return RETURN_ERR;
120 }
121
122 hal_init_done = 1;
developerc63ec4a2022-12-26 16:08:58 +0800123#endif
developeraab9e962022-04-07 12:49:36 +0800124 return RETURN_OK;
125}
126
127
128/* CcspHalEthSwGetPortStatus : */
129/**
130* @description Retrieve the current port status -- link speed, duplex mode, etc.
131
132* @param PortId -- Port ID as defined in CCSP_HAL_ETHSW_PORT
133* @param pLinkRate -- Receives the current link rate, as in CCSP_HAL_ETHSW_LINK_RATE
134* @param pDuplexMode -- Receives the current duplex mode, as in CCSP_HAL_ETHSW_DUPLEX_MODE
135* @param pStatus -- Receives the current link status, as in CCSP_HAL_ETHSW_LINK_STATUS
136
137*
138* @return The status of the operation.
139* @retval RETURN_OK if successful.
140* @retval RETURN_ERR if any error is detected
141*
142* @execution Synchronous.
143* @sideeffect None.
144
145*
146* @note This function must not suspend and must not invoke any blocking system
147* calls. It should probably just send a message to a driver event handler task.
148*
149*/
150INT
151CcspHalEthSwGetPortStatus
152 (
153 CCSP_HAL_ETHSW_PORT PortId,
154 PCCSP_HAL_ETHSW_LINK_RATE pLinkRate,
155 PCCSP_HAL_ETHSW_DUPLEX_MODE pDuplexMode,
156 PCCSP_HAL_ETHSW_LINK_STATUS pStatus
157 )
158{
159 char path[32] = {0};
160 FILE *fp = NULL;
161 char cmd[64] = {0};
162 char filepath[32] = {0};
163 char buf[32] = {0};
164 char duplex[6] = {0};
165 int link = 0;
166 int speed = 0;
developerc63ec4a2022-12-26 16:08:58 +0800167 char ifName[16] = {0};
developeraab9e962022-04-07 12:49:36 +0800168
developer67da5492022-06-28 10:45:44 +0800169 if(PortId == NULL || pLinkRate == NULL || pDuplexMode == NULL || pStatus == NULL)
170 return RETURN_ERR;
171
172 if(PortId < 1 || PortId > MAX_LAN_PORT)
173 return RETURN_ERR;
174
developerc63ec4a2022-12-26 16:08:58 +0800175#ifdef THREE_GMACS_SUPPORT
176 if(PortId == 5){
177 sprintf(ifName,"%s", "eth3");
178 }else
179#endif
180 {
181 sprintf(ifName, "lan%d", (PortId-1));
182 }
183 sprintf(path, "/sys/class/net/%s/carrier", ifName);
developeraab9e962022-04-07 12:49:36 +0800184 link = is_interface_link(path);
185
developer67da5492022-06-28 10:45:44 +0800186 if(link){
developeraab9e962022-04-07 12:49:36 +0800187 *pStatus = CCSP_HAL_ETHSW_LINK_Up;
188 }else{
189 *pStatus = CCSP_HAL_ETHSW_LINK_Down;
190 *pLinkRate = CCSP_HAL_ETHSW_LINK_NULL;
191 *pDuplexMode = CCSP_HAL_ETHSW_DUPLEX_Auto;
192 return RETURN_OK;
193 }
developerc63ec4a2022-12-26 16:08:58 +0800194 sprintf(cmd, "%s %s | grep -i speed > /tmp/%s_speed", ETHSWITCHTOOL, ifName, ifName);
developeraab9e962022-04-07 12:49:36 +0800195 system(cmd);
developerc63ec4a2022-12-26 16:08:58 +0800196 sprintf(filepath, "/tmp/%s_speed", ifName);
developeraab9e962022-04-07 12:49:36 +0800197 fp = fopen(filepath, "r");
198 if(fp != NULL)
199 {
200 fgets(buf,sizeof(buf),fp);
201 if(strstr(buf,"Unknown") == NULL){
202 sscanf(buf," Speed: %dMb/s", &speed);
203 }
204 fclose(fp);
205 }else{
206 *pLinkRate = CCSP_HAL_ETHSW_LINK_NULL;
207 *pDuplexMode = CCSP_HAL_ETHSW_DUPLEX_Auto;
208 return RETURN_OK;
209 }
210
211 if(speed)
212 {
213 memset(buf,0,sizeof(buf));
214 memset(cmd,0,sizeof(cmd));
215 memset(filepath,0,sizeof(filepath));
developerc63ec4a2022-12-26 16:08:58 +0800216 sprintf(cmd, "%s %s | grep -i duplex > /tmp/%s_duplex", ETHSWITCHTOOL, ifName, ifName);
developeraab9e962022-04-07 12:49:36 +0800217 system(cmd);
developerc63ec4a2022-12-26 16:08:58 +0800218 sprintf(filepath, "/tmp/%s_duplex", ifName);
developeraab9e962022-04-07 12:49:36 +0800219 fp = fopen(filepath, "r");
220 if(fp != NULL)
221 {
222 fgets(buf,sizeof(buf),fp);
223 if(strstr(buf,"Unknown") == NULL){
224 sscanf(buf," Duplex: %s", duplex);
225 }
226 fclose(fp);
227 if(!strcmp(duplex,"Full"))
228 *pDuplexMode = CCSP_HAL_ETHSW_DUPLEX_Full;
229 else
230 *pDuplexMode = CCSP_HAL_ETHSW_DUPLEX_Half;
231 }
232 }
233 switch (speed)
234 {
235 case 0:
236 {
237 *pLinkRate = CCSP_HAL_ETHSW_LINK_Auto;
238 *pDuplexMode = CCSP_HAL_ETHSW_DUPLEX_Auto;
239 break;
240 }
241
242 case 10:
243 {
244 *pLinkRate = CCSP_HAL_ETHSW_LINK_10Mbps;
245 break;
246 }
247
248 case 100:
249 {
250 *pLinkRate = CCSP_HAL_ETHSW_LINK_100Mbps;
251 break;
252 }
253
254 case 1000:
255 {
256 *pLinkRate = CCSP_HAL_ETHSW_LINK_1Gbps;
257 break;
258 }
259
260 case 2500:
261 {
262 *pLinkRate = CCSP_HAL_ETHSW_LINK_2_5Gbps;
263 break;
264 }
265
266 case 5000:
267 {
268 *pLinkRate = CCSP_HAL_ETHSW_LINK_5Gbps;
269 break;
270 }
271
272 case 10000:
273 {
274 *pLinkRate = CCSP_HAL_ETHSW_LINK_10Gbps;
275 break;
276 }
277
278 default:
279 {
280 CcspHalEthSwTrace(("Unsupported link rate %d port id %d\n",speed, PortId));
281 return RETURN_ERR;
282 }
283 }
284
285 return RETURN_OK;
286}
287
288
289/* CcspHalEthSwGetPortCfg : */
290/**
291* @description Retrieve the current port config -- link speed, duplex mode, etc.
292
293* @param PortId -- Port ID as defined in CCSP_HAL_ETHSW_PORT
294* @param pLinkRate -- Receives the current link rate, as in CCSP_HAL_ETHSW_LINK_RATE
295* @param pDuplexMode -- Receives the current duplex mode, as in CCSP_HAL_ETHSW_DUPLEX_MODE
296
297*
298* @return The status of the operation.
299* @retval RETURN_OK if successful.
300* @retval RETURN_ERR if any error is detected
301*
302* @execution Synchronous.
303* @sideeffect None.
304
305*
306* @note This function must not suspend and must not invoke any blocking system
307* calls. It should probably just send a message to a driver event handler task.
308*
309*/
310INT
311CcspHalEthSwGetPortCfg
312 (
313 CCSP_HAL_ETHSW_PORT PortId,
314 PCCSP_HAL_ETHSW_LINK_RATE pLinkRate,
315 PCCSP_HAL_ETHSW_DUPLEX_MODE pDuplexMode
316 )
317{
318
319 FILE *fp = NULL;
320 char cmd[64] = {0};
321 char filepath[32] = {0};
322 char buf[32] = {0};
323 char duplex[6] = {0};
324 int speed = 0;
developerc63ec4a2022-12-26 16:08:58 +0800325 char ifName[16] = {0};
developeraab9e962022-04-07 12:49:36 +0800326
developer67da5492022-06-28 10:45:44 +0800327 if(PortId == NULL || pLinkRate == NULL || pDuplexMode == NULL)
328 return RETURN_ERR;
329
330 if(PortId < 1 || PortId > MAX_LAN_PORT)
331 return RETURN_ERR;
developerc63ec4a2022-12-26 16:08:58 +0800332
333#ifdef THREE_GMACS_SUPPORT
334 if(PortId == 5){
335 sprintf(ifName,"%s", "eth3");
336 }else
337#endif
338 {
339 sprintf(ifName, "lan%d", (PortId-1));
340 }
341
342 sprintf(cmd, "%s %s | grep -i speed > /tmp/%s_speed", ETHSWITCHTOOL, ifName, ifName);
developeraab9e962022-04-07 12:49:36 +0800343 system(cmd);
developerc63ec4a2022-12-26 16:08:58 +0800344 sprintf(filepath, "/tmp/%s_speed", ifName);
developeraab9e962022-04-07 12:49:36 +0800345 fp = fopen(filepath, "r");
346 if(fp != NULL)
347 {
348 fgets(buf,sizeof(buf),fp);
349 if(strstr(buf,"Unknown") == NULL){
350 sscanf(buf," Speed: %dMb/s", &speed);
351 }
352 fclose(fp);
353 }else{
354 *pLinkRate = CCSP_HAL_ETHSW_LINK_NULL;
355 *pDuplexMode = CCSP_HAL_ETHSW_DUPLEX_Auto;
356 return RETURN_OK;
357 }
358
359 if(speed)
360 {
361 memset(buf,0,sizeof(buf));
362 memset(cmd,0,sizeof(cmd));
363 memset(filepath,0,sizeof(filepath));
developerc63ec4a2022-12-26 16:08:58 +0800364 sprintf(cmd, "%s %s | grep -i duplex > /tmp/%s_duplex", ETHSWITCHTOOL, ifName, ifName);
developeraab9e962022-04-07 12:49:36 +0800365 system(cmd);
developerc63ec4a2022-12-26 16:08:58 +0800366 sprintf(filepath, "/tmp/%s_duplex", ifName);
developeraab9e962022-04-07 12:49:36 +0800367 fp = fopen(filepath, "r");
368 if(fp != NULL)
369 {
370 fgets(buf,sizeof(buf),fp);
371 if(strstr(buf,"Unknown") == NULL){
372 sscanf(buf," Duplex: %s", duplex);
373 }
374 fclose(fp);
375 if(!strcmp(duplex,"Full"))
376 *pDuplexMode = CCSP_HAL_ETHSW_DUPLEX_Full;
377 else
378 *pDuplexMode = CCSP_HAL_ETHSW_DUPLEX_Half;
379 }
380 }
381 switch (speed)
382 {
383 case 0:
384 {
385 *pLinkRate = CCSP_HAL_ETHSW_LINK_Auto;
386 *pDuplexMode = CCSP_HAL_ETHSW_DUPLEX_Auto;
387 break;
388 }
389
390 case 10:
391 {
392 *pLinkRate = CCSP_HAL_ETHSW_LINK_10Mbps;
393 break;
394 }
395
396 case 100:
397 {
398 *pLinkRate = CCSP_HAL_ETHSW_LINK_100Mbps;
399 break;
400 }
401
402 case 1000:
403 {
404 *pLinkRate = CCSP_HAL_ETHSW_LINK_1Gbps;
405 break;
406 }
407
408 case 2500:
409 {
410 *pLinkRate = CCSP_HAL_ETHSW_LINK_2_5Gbps;
411 break;
412 }
413
414 case 5000:
415 {
416 *pLinkRate = CCSP_HAL_ETHSW_LINK_5Gbps;
417 break;
418 }
419
420 case 10000:
421 {
422 *pLinkRate = CCSP_HAL_ETHSW_LINK_10Gbps;
423 break;
424 }
425
426 default:
427 {
428 CcspHalEthSwTrace(("Unsupported link rate %d port id %d\n",speed, PortId));
429 return RETURN_ERR;
430 }
431 }
432
433 return RETURN_OK;
434}
435
436
437/* CcspHalEthSwSetPortCfg : */
438/**
439* @description Set the port configuration -- link speed, duplex mode
440
441* @param PortId -- Port ID as defined in CCSP_HAL_ETHSW_PORT
442* @param LinkRate -- Set the link rate, as in CCSP_HAL_ETHSW_LINK_RATE
443* @param DuplexMode -- Set the duplex mode, as in CCSP_HAL_ETHSW_DUPLEX_MODE
444
445*
446* @return The status of the operation.
447* @retval RETURN_OK if successful.
448* @retval RETURN_ERR if any error is detected
449*
450* @execution Synchronous.
451* @sideeffect None.
452
453*
454* @note This function must not suspend and must not invoke any blocking system
455* calls. It should probably just send a message to a driver event handler task.
456*
457*/
458INT
459CcspHalEthSwSetPortCfg
460 (
461 CCSP_HAL_ETHSW_PORT PortId,
462 CCSP_HAL_ETHSW_LINK_RATE LinkRate,
463 CCSP_HAL_ETHSW_DUPLEX_MODE DuplexMode
464 )
465{
466 CcspHalEthSwTrace(("set port %d LinkRate to %d, DuplexMode to %d", PortId, LinkRate, DuplexMode));
developer67da5492022-06-28 10:45:44 +0800467
468 if(PortId < 1 || PortId > MAX_LAN_PORT)
469 return RETURN_ERR;
developeraab9e962022-04-07 12:49:36 +0800470
471 char cmd[128] = {0};
472 char setduplex[6] = {0};
developerc63ec4a2022-12-26 16:08:58 +0800473 char ifName[16] = {0};
developeraab9e962022-04-07 12:49:36 +0800474
developer67da5492022-06-28 10:45:44 +0800475 if(DuplexMode == 2 || DuplexMode == 0)
developeraab9e962022-04-07 12:49:36 +0800476 strcpy(setduplex,"full");
developer67da5492022-06-28 10:45:44 +0800477 else if (DuplexMode == 1)
developeraab9e962022-04-07 12:49:36 +0800478 strcpy(setduplex,"half");
developer67da5492022-06-28 10:45:44 +0800479 else
480 return RETURN_ERR;
developeraab9e962022-04-07 12:49:36 +0800481
developerc63ec4a2022-12-26 16:08:58 +0800482#ifdef THREE_GMACS_SUPPORT
483 if(PortId == 5){
484 sprintf(ifName,"%s", "eth3");
485 }else
486#endif
487 {
488 sprintf(ifName, "lan%d", (PortId-1));
489 }
490
developeraab9e962022-04-07 12:49:36 +0800491 switch (LinkRate)
492 {
493 case CCSP_HAL_ETHSW_LINK_10Mbps:
494 {
developerc63ec4a2022-12-26 16:08:58 +0800495 sprintf(cmd,"%s -s %s speed %d duplex %s", ETHSWITCHTOOL, ifName, 10, setduplex);
developeraab9e962022-04-07 12:49:36 +0800496 system(cmd);
497 break;
498 }
499
500 case CCSP_HAL_ETHSW_LINK_100Mbps:
501 {
developerc63ec4a2022-12-26 16:08:58 +0800502 sprintf(cmd,"%s -s %s speed %d duplex %s", ETHSWITCHTOOL, ifName, 100, setduplex);
developeraab9e962022-04-07 12:49:36 +0800503 system(cmd);
504 break;
505 }
506
507 case CCSP_HAL_ETHSW_LINK_1Gbps:
developerc63ec4a2022-12-26 16:08:58 +0800508 {
509 sprintf(cmd,"%s -s %s speed %d duplex full", ETHSWITCHTOOL, ifName, 1000);
510 system(cmd);
511 break;
512 }
developeraab9e962022-04-07 12:49:36 +0800513 case CCSP_HAL_ETHSW_LINK_2_5Gbps:
514 case CCSP_HAL_ETHSW_LINK_5Gbps:
515 case CCSP_HAL_ETHSW_LINK_10Gbps:
516 case CCSP_HAL_ETHSW_LINK_Auto:
517 {
developerc63ec4a2022-12-26 16:08:58 +0800518 sprintf(cmd,"%s -s %s autoneg on", ETHSWITCHTOOL, ifName);
developeraab9e962022-04-07 12:49:36 +0800519 system(cmd);
520 break;
521 }
522 default:
523 {
524 CcspHalEthSwTrace(("Unsupported link rate %d port id %d\n",LinkRate, PortId));
525 return RETURN_ERR;
526 }
527 }
528
529 return RETURN_OK;
530}
531
532
533/* CcspHalEthSwGetPortAdminStatus : */
534/**
535* @description Retrieve the current port admin status.
536
537* @param PortId -- Port ID as defined in CCSP_HAL_ETHSW_PORT
538* @param pAdminStatus -- Receives the current admin status
539
540*
541* @return The status of the operation.
542* @retval RETURN_OK if successful.
543* @retval RETURN_ERR if any error is detected
544*
545* @execution Synchronous.
546* @sideeffect None.
547
548*
549* @note This function must not suspend and must not invoke any blocking system
550* calls. It should probably just send a message to a driver event handler task.
551*
552*/
553INT
554CcspHalEthSwGetPortAdminStatus
555 (
556 CCSP_HAL_ETHSW_PORT PortId,
557 PCCSP_HAL_ETHSW_ADMIN_STATUS pAdminStatus
558 )
559{
developer67da5492022-06-28 10:45:44 +0800560 if(PortId == NULL || pAdminStatus == NULL)
561 return RETURN_ERR;
562
563 CcspHalEthSwTrace(("port id %d", PortId));
564
565 if(PortId < 1 || PortId > MAX_LAN_PORT)
566 return RETURN_ERR;
developeraab9e962022-04-07 12:49:36 +0800567
568 int sockfd;
569 struct ifreq ifr;
570
571 if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
572 {
573 printf("====> open socket fail \n");
574 return RETURN_ERR;
575 }
576
577 memset(&ifr, 0, sizeof(ifr));
578 snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", "eth1");
579
580 if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0)
581 {
582 printf("====> ioctl open socket fail \n");
583 close(sockfd);
584 return RETURN_ERR;
585 }
586
587 close(sockfd);
588 if(ifr.ifr_flags & IFF_UP)
589 *pAdminStatus = CCSP_HAL_ETHSW_AdminUp;
590 else
591 *pAdminStatus = CCSP_HAL_ETHSW_AdminDown;
developer67da5492022-06-28 10:45:44 +0800592
593 if(admin_status)
594 *pAdminStatus = CCSP_HAL_ETHSW_AdminDown;
595
developeraab9e962022-04-07 12:49:36 +0800596 return RETURN_OK;
597}
598
599/* CcspHalEthSwSetPortAdminStatus : */
600/**
601* @description Set the ethernet port admin status
602
603* @param AdminStatus -- set the admin status, as defined in CCSP_HAL_ETHSW_ADMIN_STATUS
604
605*
606* @return The status of the operation.
607* @retval RETURN_OK if successful.
608* @retval RETURN_ERR if any error is detected
609*
610* @execution Synchronous.
611* @sideeffect None.
612
613*
614* @note This function must not suspend and must not invoke any blocking system
615* calls. It should probably just send a message to a driver event handler task.
616*
617*/
618INT
619CcspHalEthSwSetPortAdminStatus
620 (
621 CCSP_HAL_ETHSW_PORT PortId,
622 CCSP_HAL_ETHSW_ADMIN_STATUS AdminStatus
623 )
624{
625 CcspHalEthSwTrace(("set port %d AdminStatus to %d", PortId, AdminStatus));
developer67da5492022-06-28 10:45:44 +0800626 if(AdminStatus < CCSP_HAL_ETHSW_AdminUp || AdminStatus > CCSP_HAL_ETHSW_AdminTest)
627 return RETURN_ERR;
628 if(PortId < 1 || PortId > MAX_LAN_PORT)
629 return RETURN_ERR;
630
developerc63ec4a2022-12-26 16:08:58 +0800631 char cmd1[32] = {0};
632 char cmd2[32] = {0};
633 char interface[8] = {0};
634 char path[32] = {0};
635
developeraab9e962022-04-07 12:49:36 +0800636 strcpy(path,"/sys/class/net/eth1");
637
638 int eth_if=is_interface_exists(path);
639
640 if(eth_if == 0 )
641 return RETURN_ERR;
642
developeraab9e962022-04-07 12:49:36 +0800643 strcpy(interface,"eth1");
644
645 sprintf(cmd1,"ip link set %s up",interface);
646 sprintf(cmd2,"ip link set %s down",interface);
647
648 switch (PortId)
649 {
650 case CCSP_HAL_ETHSW_EthPort1:
651 case CCSP_HAL_ETHSW_EthPort2:
652 case CCSP_HAL_ETHSW_EthPort3:
653 case CCSP_HAL_ETHSW_EthPort4:
654 {
developer67da5492022-06-28 10:45:44 +0800655
developeraab9e962022-04-07 12:49:36 +0800656 {
657 if(AdminStatus==0)
658 {
659 system(cmd1);
660 admin_status=0;
661 }
662 else
663 {
developer67da5492022-06-28 10:45:44 +0800664 //system(cmd2);
developeraab9e962022-04-07 12:49:36 +0800665 admin_status=1;
666 }
667 }
668 break;
669 }
670 default:
671 CcspHalEthSwTrace(("Unsupported port id %d", PortId));
672 return RETURN_ERR;
673 }
674 return RETURN_OK;
675}
676
677
678/* CcspHalEthSwSetAgingSpeed : */
679/**
680* @description Set the ethernet port configuration -- admin up/down, link speed, duplex mode
681
682* @param PortId -- Port ID as defined in CCSP_HAL_ETHSW_PORT
683* @param AgingSpeed -- integer value of aging speed
684*
685* @return The status of the operation.
686* @retval RETURN_OK if successful.
687* @retval RETURN_ERR if any error is detected
688*
689* @execution Synchronous.
690* @sideeffect None.
691
692*
693* @note This function must not suspend and must not invoke any blocking system
694* calls. It should probably just send a message to a driver event handler task.
695*
696*/
697INT
698CcspHalEthSwSetAgingSpeed
699 (
700 CCSP_HAL_ETHSW_PORT PortId,
701 INT AgingSpeed
702 )
703{
704 CcspHalEthSwTrace(("set port %d aging speed to %d", PortId, AgingSpeed));
developer67da5492022-06-28 10:45:44 +0800705 if(AgingSpeed < 0 || AgingSpeed > 300)
706 return RETURN_ERR;
707 if(PortId < 1)
708 return RETURN_ERR;
developeraab9e962022-04-07 12:49:36 +0800709 return RETURN_OK;
710}
711
712
713/* CcspHalEthSwLocatePortByMacAddress : */
714/**
715* @description Retrieve the port number that the specificed MAC address is associated with (seen)
716
717* @param pMacAddr -- Specifies the MAC address -- 6 bytes
718* @param pPortId -- Receives the found port number that the MAC address is seen on
719
720*
721* @return The status of the operation.
722* @retval RETURN_OK if successful.
723* @retval RETURN_ERR if any error is detected
724*
725* @execution Synchronous.
726* @sideeffect None.
727
728*
729* @note This function must not suspend and must not invoke any blocking system
730* calls. It should probably just send a message to a driver event handler task.
731*
732*/
733INT
734CcspHalEthSwLocatePortByMacAddress
735 (
736 unsigned char * pMacAddr,
737 INT * pPortId
738 )
739{
developer67da5492022-06-28 10:45:44 +0800740 if (pMacAddr == NULL)
741 return RETURN_ERR;
742
developeraab9e962022-04-07 12:49:36 +0800743 CcspHalEthSwTrace
744 ((
developer67da5492022-06-28 10:45:44 +0800745 "%s -- search for MAC address %02x:%02x:%02x:%02x:%02x:%02x",
developeraab9e962022-04-07 12:49:36 +0800746 __FUNCTION__,
747 pMacAddr[0], pMacAddr[1], pMacAddr[2],
748 pMacAddr[3], pMacAddr[4], pMacAddr[5]
749 ));
750
developer67da5492022-06-28 10:45:44 +0800751 char cmd[128] = {0};
752 char buf[128] = {0};
753 char foundmac[18] = {0};
754 int port = 0;
755 FILE *fp = NULL;
756
757 sprintf(foundmac,"%02x:%02x:%02x:%02x:%02x:%02x",pMacAddr[0], pMacAddr[1], pMacAddr[2], pMacAddr[3], pMacAddr[4], pMacAddr[5]);
758
759 snprintf(cmd,128, "bridge fdb show | grep %s | awk '$0 ~ /master/{print $3} '", foundmac);
760
761 fp = popen(cmd, "r");
762 if(fp != NULL)
763 {
764 if(fgets(buf,sizeof(buf),fp) != NULL)
765 {
766 pclose(fp);
767 if (strncmp(buf, "lan",3))
768 {
developerc63ec4a2022-12-26 16:08:58 +0800769#ifdef THREE_GMACS_SUPPORT
770 if (!strncmp(buf, "eth3",4))
771 {
772 *pPortId = 5;
773 return RETURN_OK;
774 }
775#endif
developer67da5492022-06-28 10:45:44 +0800776 return RETURN_ERR;
777 }else{
778 sscanf(buf,"lan%d",&port);
779 *pPortId = port+1;
780 return RETURN_OK;
781 }
782 }
783 pclose(fp);
784 }
785 return RETURN_ERR;
developeraab9e962022-04-07 12:49:36 +0800786}
787
788//For Getting Current Interface Name from corresponding hostapd configuration
789void GetInterfaceName(char *interface_name, char *conf_file)
790{
791 FILE *fp = NULL;
792 char path[MAX_BUF_SIZE] = {0},output_string[MAX_BUF_SIZE] = {0},fname[MAX_BUF_SIZE] = {0};
793 int count = 0;
794 char *interface = NULL;
795
796 fp = fopen(conf_file, "r");
797 if(fp == NULL)
798 {
799 printf("conf_file %s not exists \n", conf_file);
800 return;
801 }
802 fclose(fp);
803
804 sprintf(fname,"%s%s%s","cat ",conf_file," | grep interface=");
805 fp = popen(fname,"r");
806 if(fp == NULL)
807 {
808 printf("Failed to run command in Function %s\n",__FUNCTION__);
809 strcpy(interface_name, "");
810 return;
811 }
812 if(fgets(path, sizeof(path)-1, fp) != NULL)
813 {
814 interface = strchr(path,'=');
815
816 if(interface != NULL)
developerc63ec4a2022-12-26 16:08:58 +0800817 strncpy(output_string, interface+1, sizeof(output_string));
developeraab9e962022-04-07 12:49:36 +0800818 }
819
820 for(count = 0;output_string[count]!='\n';count++)
821 interface_name[count] = output_string[count];
822 interface_name[count]='\0';
823
824 fprintf(stderr,"Interface name %s \n", interface_name);
825
826 pclose(fp);
827}
828/* CcspHalExtSw_getAssociatedDevice : */
829/**
830* @description Collected the active wired clients information
831
832* @param output_array_size -- Size of the active wired connected clients
833* @param output_struct -- Structure of wired clients informations
834
835*
836* @return The status of the operation.
837* @retval RETURN_OK if successful.
838* @retval RETURN_ERR if any error is detected
839*
840*/
841
842INT CcspHalExtSw_getAssociatedDevice(ULONG *output_array_size, eth_device_t **output_struct)
843{
844 CHAR buf[MAX_BUF_SIZE] = {0},str[MAX_BUF_SIZE] = {0},interface_name[50] = {0},macAddr[50] = {0};
845 FILE *fp = NULL,*fp1 = NULL;
846 INT count = 0,str_count = 0;
847 ULONG maccount = 0,eth_count = 0;
848 INT arr[MACADDRESS_SIZE] = {0};
849 UCHAR mac[MACADDRESS_SIZE] = {0};
850 CHAR ipAddr[50],stub[50],phyAddr[50],ifName[32],status[32];
851 int ret;
852 if(output_struct == NULL)
853 {
854 printf("\nNot enough memory\n");
855 return RETURN_ERR;
856 }
developerc63ec4a2022-12-26 16:08:58 +0800857
858 system("echo -n > /tmp/ethernetmac.txt");
859
developeraab9e962022-04-07 12:49:36 +0800860 system("cat /nvram/dnsmasq.leases | cut -d ' ' -f2 > /tmp/connected_mac.txt"); //storing the all associated device information in tmp folder
861 //storing the private wifi associated device iformation in tmp folder
862 GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
863 sprintf(buf,"iw dev %s station dump | grep Station | cut -d ' ' -f2 > /tmp/Associated_Devices.txt",interface_name);
864 system(buf);
865 GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
866 sprintf(buf,"iw dev %s station dump | grep Station | cut -d ' ' -f2 >> /tmp/Associated_Devices.txt",interface_name);
867 system(buf);
868
869 system("diff /tmp/Associated_Devices.txt /tmp/connected_mac.txt | grep \"^+\" | cut -c2- | sed -n '1!p' > /tmp/ethernet_connected_clients.txt"); //separating the ethernet associated device information from connected_mac test file
870 fp=popen("cat /tmp/ethernet_connected_clients.txt | wc -l","r"); // For getting the ethernet connected mac count
871 if(fp == NULL)
872 return RETURN_ERR;
873 else
874 {
875 fgets(buf,MAX_BUF_SIZE,fp);
developerc63ec4a2022-12-26 16:08:58 +0800876 maccount = strtol(buf, NULL, 10);
developeraab9e962022-04-07 12:49:36 +0800877 fprintf(stderr,"ethernet umac is %d \n",maccount);
878 }
879 pclose(fp);
880 eth_device_t *temp=NULL;
881 temp = (eth_device_t*)calloc(1, sizeof(eth_device_t)*maccount);
882 if(temp == NULL)
883 {
884 fprintf(stderr,"Not enough memory \n");
885 return RETURN_ERR;
886 }
887 fp=fopen("/tmp/ethernet_connected_clients.txt","r"); // reading the ethernet associated device information
888 if(fp == NULL)
889 {
890 *output_struct = NULL;
891 *output_array_size = 0;
developerc63ec4a2022-12-26 16:08:58 +0800892 free(temp);
developeraab9e962022-04-07 12:49:36 +0800893 return RETURN_ERR;
894 }
895 else
896 {
897 for(count = 0;count < maccount ; count++)
898 {
899 fgets(str,MAX_BUF_SIZE,fp);
900 for(str_count = 0;str[str_count]!='\n';str_count++)
901 macAddr[str_count] = str[str_count];
902 macAddr[str_count] = '\0';
903 system("ip nei show | grep brlan0 > /tmp/arp_cache");
904 fp1=fopen("/tmp/arp_cache","r");
developerc63ec4a2022-12-26 16:08:58 +0800905 if(fp1 == NULL){
906 fclose(fp);
907 free(temp);
developeraab9e962022-04-07 12:49:36 +0800908 return RETURN_ERR;
developerc63ec4a2022-12-26 16:08:58 +0800909 }
developeraab9e962022-04-07 12:49:36 +0800910 while(fgets(buf,sizeof(buf),fp1) != NULL)
911 {
912 if ( strstr(buf, "FAILED") != 0 )
913 continue;
914 /*
915Sample:
91610.0.0.208 dev brlan0 lladdr d4:be:d9:99:7f:47 STALE
91710.0.0.107 dev brlan0 lladdr 64:a2:f9:d2:f5:67 REACHABLE
918 */
919 ret = sscanf(buf, LM_ARP_ENTRY_FORMAT,
920 ipAddr,
921 stub,
922 ifName,
923 stub,
924 phyAddr,
925 status);
926 if(ret != 6)
927 continue;
928 if(strcmp(phyAddr,macAddr) == 0)
929 {
930 memset(buf,0,sizeof(buf));
931 if(strcmp(status,"REACHABLE") == 0)
932 {
933 sprintf(buf,"echo %s >> /tmp/ethernetmac.txt",macAddr);
934 system(buf);
935 eth_count++;
936 break;
937 }
938 else if((strcmp(status,"STALE") == 0) || (strcmp(status,"DELAY")))
939 {
940 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipAddr);
941 fprintf(stderr,"buf is %s and MACADRRESS %s\n",buf,macAddr);
942 if (WEXITSTATUS(system(buf)) == 0)
943 {
944 fprintf(stderr,"Inside STALE SUCCESS \n");
945 memset(buf,0,sizeof(buf));
946 sprintf(buf,"echo %s >> /tmp/ethernetmac.txt",macAddr);
947 system(buf);
948 eth_count++;
949 break;
950 }
951 }
952 else
953 {
954 fprintf(stderr,"Running in different state \n");
955 break;
956 }
957 }
958 else
959 fprintf(stderr,"MAcAddress is not valid \n");
960 }
961 fclose(fp1);
962 }
963 }
964 fclose(fp);
965 fp=fopen("/tmp/ethernetmac.txt","r");
966 if(fp == NULL)
967 {
968 *output_struct = NULL;
969 *output_array_size = 0;
developerc63ec4a2022-12-26 16:08:58 +0800970 free(temp);
developeraab9e962022-04-07 12:49:36 +0800971 return RETURN_OK;
972 }
973 else
974 {
975 memset(buf,0,sizeof(buf));
976 for(count = 0;count < eth_count ; count++)
977 {
978 fgets(buf,sizeof(buf),fp);
developer67da5492022-06-28 10:45:44 +0800979 if(MACADDRESS_SIZE == sscanf(buf, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
980 {
981 for( int ethclientindex = 0; ethclientindex < 6; ++ethclientindex )
developeraab9e962022-04-07 12:49:36 +0800982 {
developer67da5492022-06-28 10:45:44 +0800983 mac[ethclientindex] = (unsigned char) arr[ethclientindex];
developeraab9e962022-04-07 12:49:36 +0800984 }
developer67da5492022-06-28 10:45:44 +0800985 memcpy(temp[count].eth_devMacAddress,mac,(sizeof(unsigned char))*6);
986 fprintf(stderr,"MAC %d = %X:%X:%X:%X:%X:%X \n", count, temp[count].eth_devMacAddress[0],temp[count].eth_devMacAddress[1], temp[count].eth_devMacAddress[2], temp[count].eth_devMacAddress[3], temp[count].eth_devMacAddress[4], temp[count].eth_devMacAddress[5]);
987 }
988 temp[count].eth_port= 0;
989 CcspHalEthSwLocatePortByMacAddress(temp[count].eth_devMacAddress, &temp[count].eth_port);
990 temp[count].eth_vlanid=-1;
991 FILE *fp2 = NULL;
992 char cmd[64] = {0};
993 char filepath[32] = {0};
994 char buffer[32] = {0};
developerc63ec4a2022-12-26 16:08:58 +0800995#ifdef THREE_GMACS_SUPPORT
996 if (temp[count].eth_port == 5){
997 sprintf(filepath, "/sys/class/net/eth3/speed");
998 }else
999#endif
1000 {
1001 sprintf(filepath, "/sys/class/net/lan%d/speed",(temp[count].eth_port-1));
1002 }
developer67da5492022-06-28 10:45:44 +08001003 fp2 = fopen(filepath, "r");
1004 if(fp2 != NULL)
1005 {
1006 fgets(buffer,sizeof(buffer),fp2);
developerc63ec4a2022-12-26 16:08:58 +08001007 temp[count].eth_devTxRate = strtol(buffer, NULL, 10);
developer67da5492022-06-28 10:45:44 +08001008 temp[count].eth_Active=1;
1009 fclose(fp2);
1010 }else{
1011 temp[count].eth_devTxRate= -1;
1012 temp[count].eth_Active=0;
1013 }
1014 temp[count].eth_devRxRate = temp[count].eth_devTxRate;
developeraab9e962022-04-07 12:49:36 +08001015 }
1016 }
1017 fclose(fp);
1018 *output_struct = temp;
1019 *output_array_size = eth_count;
1020 fprintf(stderr,"Connected Active ethernet clients count is %ld \n",*output_array_size);
1021 return RETURN_OK;
1022}
1023
1024/* CcspHalExtSw_getEthWanEnable */
1025/**
1026* @description Return the Ethwan Enbale status
1027
1028* @param enable -- Having status of WANMode ( Ethernet,DOCSIS)
1029
1030*
1031* @return The status of the operation.
1032* @retval RETURN_OK if successful.
1033* @retval RETURN_ERR if any error is detected
1034*
1035*/
1036
1037INT CcspHalExtSw_getEthWanEnable(BOOLEAN *enable)
1038{
1039 int sockfd;
1040 struct ifreq ifr;
1041
developer67da5492022-06-28 10:45:44 +08001042 if (enable == NULL)
1043 return RETURN_ERR;
developeraab9e962022-04-07 12:49:36 +08001044 if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
1045 {
1046 printf("====> open socket fail \n");
1047 return RETURN_ERR;
1048 }
1049
1050 memset(&ifr, 0, sizeof(ifr));
developer2b1a9142022-04-14 18:10:59 +08001051 snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", ETH_WAN_INTERFACE);
developeraab9e962022-04-07 12:49:36 +08001052
1053 if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0)
1054 {
1055 printf("====> ioctl open socket fail \n");
1056 close(sockfd);
1057 return RETURN_ERR;
1058 }
1059
1060 close(sockfd);
1061 *enable = ifr.ifr_flags & IFF_UP;
1062 return RETURN_OK;
1063}
1064
1065/* CcspHalExtSw_getEthWanPort: */
1066/**
1067* @description Return the ethwan port
1068
1069* @param port -- having ethwan port
1070
1071*
1072* @return The status of the operation.
1073* @retval RETURN_OK if successful.
1074* @retval RETURN_ERR if any error is detected
1075*
1076*/
1077
1078INT CcspHalExtSw_getEthWanPort(UINT *Port)
1079{
developer67da5492022-06-28 10:45:44 +08001080 if(Port == NULL)
1081 return RETURN_ERR;
1082
developeraab9e962022-04-07 12:49:36 +08001083 *Port = 6;
1084 return RETURN_OK;
1085}
1086
1087/* CcspHalExtSw_setEthWanEnable : */
1088/**
1089* @description setting the ethwan enable status
1090
1091* @enable -- Switch from ethernet mode to docsis mode or vice-versa
1092
1093*
1094* @return The status of the operation.
1095* @retval RETURN_OK if successful.
1096* @retval RETURN_ERR if any error is detected
1097*
1098*/
1099
1100INT CcspHalExtSw_setEthWanEnable(BOOLEAN enable)
1101{
1102 char cmd[32] = {0};
1103
developer2b1a9142022-04-14 18:10:59 +08001104 sprintf(cmd,"ifconfig %s %s",ETH_WAN_INTERFACE, enable ? "up":"down");
developeraab9e962022-04-07 12:49:36 +08001105 system(cmd);
1106
1107 return RETURN_OK;
1108}
1109
1110
1111/* CcspHalExtSw_setEthWanPort : */
1112/**
1113* @description Need to set the ethwan port
1114
1115* @param port -- Setting the ethwan port
1116
1117*
1118* @return The status of the operation.
1119* @retval RETURN_OK if successful.
1120* @retval RETURN_ERR if any error is detected
1121*
1122*/
1123
1124INT CcspHalExtSw_setEthWanPort(UINT Port)
1125{
developer67da5492022-06-28 10:45:44 +08001126 if(Port != 6)
1127 return RETURN_ERR;
developeraab9e962022-04-07 12:49:36 +08001128 return RETURN_OK;
1129}
1130
1131INT GWP_GetEthWanLinkStatus()
1132{
developerc63ec4a2022-12-26 16:08:58 +08001133 int link = 0;
1134 char path[32] = {0};
developer2b1a9142022-04-14 18:10:59 +08001135
developerc63ec4a2022-12-26 16:08:58 +08001136 sprintf(path, "/sys/class/net/erouter0/carrier");
1137 link = is_interface_link(path);
developer2b1a9142022-04-14 18:10:59 +08001138
developerc63ec4a2022-12-26 16:08:58 +08001139 if(link){
1140 return 1;
1141 }else{
1142 return 0;
1143 }
developeraab9e962022-04-07 12:49:36 +08001144}
1145
developer2b1a9142022-04-14 18:10:59 +08001146#if defined(FEATURE_RDKB_WAN_MANAGER)
1147void *ethsw_thread_main(void *context __attribute__((unused)))
1148{
1149 int previousLinkDetected = 0;
1150 int currentLinkDeteced = 0;
1151 int timeout = 0;
1152 int file = 0;
1153
1154 while(timeout != 180)
1155 {
1156 if (file == access(ETH_INITIALIZE, R_OK))
1157 {
1158 CcspHalEthSwTrace(("Eth agent initialized \n"));
1159 break;
1160 }
1161 else
1162 {
1163 timeout = timeout+1;
1164 sleep(1);
1165 }
1166 }
1167
1168 while(1)
1169 {
1170 currentLinkDeteced = GWP_GetEthWanLinkStatus();
developer2b1a9142022-04-14 18:10:59 +08001171 if (currentLinkDeteced != previousLinkDetected)
1172 {
1173 if (currentLinkDeteced)
1174 {
1175 CcspHalEthSwTrace(("send_link_event: Got Link UP Event\n"));
1176 ethWanCallbacks.pGWP_act_EthWanLinkUP();
1177 }
1178 else
1179 {
1180 CcspHalEthSwTrace(("send_link_event: Got Link DOWN Event\n"));
1181 ethWanCallbacks.pGWP_act_EthWanLinkDown();
1182 }
1183 previousLinkDetected = currentLinkDeteced;
1184 }
1185 sleep(5);
1186 }
1187
1188 return NULL;
1189}
1190#endif
developeraab9e962022-04-07 12:49:36 +08001191void GWP_RegisterEthWan_Callback(appCallBack *obj) {
developer2b1a9142022-04-14 18:10:59 +08001192#if defined(FEATURE_RDKB_WAN_MANAGER)
1193 int rc;
1194
1195 if (obj == NULL) {
1196 rc = RETURN_ERR;
1197 } else {
1198 ethWanCallbacks.pGWP_act_EthWanLinkUP = obj->pGWP_act_EthWanLinkUP;
1199 ethWanCallbacks.pGWP_act_EthWanLinkDown = obj->pGWP_act_EthWanLinkDown;
1200 rc = RETURN_OK;
1201 }
1202#endif
developeraab9e962022-04-07 12:49:36 +08001203}
1204
1205INT GWP_GetEthWanInterfaceName
1206(
1207 unsigned char * Interface,
1208 ULONG maxSize
1209)
1210{
1211 //Maxsize param should be minimum 4charecters(eth0) including NULL charecter
1212 if( ( Interface == NULL ) || ( maxSize < ( strlen( ETH_WAN_IFNAME ) + 1 ) ) )
1213 {
1214 printf("ERROR: Invalid argument. \n");
1215 return RETURN_ERR;
1216 }
1217 snprintf(Interface, maxSize, "%s", ETH_WAN_IFNAME);
1218 return RETURN_OK;
1219}