• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/drivers/char/rtl8365mb/
1/*
2 * Copyright (C) 2013 Realtek Semiconductor Corp.
3 * All Rights Reserved.
4 *
5 * This program is the proprietary software of Realtek Semiconductor
6 * Corporation and/or its licensors, and only be used, duplicated,
7 * modified or distributed under the authorized license from Realtek.
8 *
9 * ANY USE OF THE SOFTWARE OTHER THAN AS AUTHORIZED UNDER
10 * THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
11 *
12 * $Revision: 50498 $
13 * $Date: 2014-08-21 14:59:13 +0800 (������, 21 ������ 2014) $
14 *
15 * Purpose : RTK switch high-level API for RTL8367/RTL8367C
16 * Feature : Here is a list of all functions and variables in L2 module.
17 *
18 */
19
20#include <rtk_switch.h>
21#include <rtk_error.h>
22#include <l2.h>
23#ifndef __KERNEL__
24#include <string.h>
25#else
26#include <linux/string.h>
27#endif
28
29#include <rtl8367c_asicdrv.h>
30#include <rtl8367c_asicdrv_lut.h>
31#include <rtl8367c_asicdrv_port.h>
32
33/* Function Name:
34 *      rtk_l2_init
35 * Description:
36 *      Initialize l2 module of the specified device.
37 * Input:
38 *      None
39 * Output:
40 *      None
41 * Return:
42 *      RT_ERR_OK          - OK
43 *      RT_ERR_FAILED      - Failed
44 *      RT_ERR_SMI         - SMI access error
45 * Note:
46 *      Initialize l2 module before calling any l2 APIs.
47 */
48rtk_api_ret_t rtk_l2_init(void)
49{
50    rtk_api_ret_t retVal;
51    rtk_uint32 port;
52
53    /* Check initialization state */
54    RTK_CHK_INIT_STATE();
55
56    if ((retVal = rtl8367c_setAsicLutIpMulticastLookup(DISABLED)) != RT_ERR_OK)
57        return retVal;
58
59    /*Enable CAM Usage*/
60    if ((retVal = rtl8367c_setAsicLutCamTbUsage(ENABLED)) != RT_ERR_OK)
61        return retVal;
62
63    if ((retVal = rtl8367c_setAsicLutAgeTimerSpeed(6,2)) != RT_ERR_OK)
64        return retVal;
65
66    RTK_SCAN_ALL_LOG_PORT(port)
67    {
68        if ((retVal = rtl8367c_setAsicLutLearnLimitNo(rtk_switch_port_L2P_get(port), rtk_switch_maxLutAddrNumber_get())) != RT_ERR_OK)
69            return retVal;
70    }
71
72    return RT_ERR_OK;
73}
74
75
76/* Function Name:
77 *      rtk_l2_addr_add
78 * Description:
79 *      Add LUT unicast entry.
80 * Input:
81 *      pMac - 6 bytes unicast(I/G bit is 0) mac address to be written into LUT.
82 *      pL2_data - Unicast entry parameter
83 * Output:
84 *      None
85 * Return:
86 *      RT_ERR_OK               - OK
87 *      RT_ERR_FAILED           - Failed
88 *      RT_ERR_SMI              - SMI access error
89 *      RT_ERR_PORT_ID          - Invalid port number.
90 *      RT_ERR_MAC              - Invalid MAC address.
91 *      RT_ERR_L2_FID           - Invalid FID .
92 *      RT_ERR_L2_INDEXTBL_FULL - hashed index is full of entries.
93 *      RT_ERR_INPUT            - Invalid input parameters.
94 * Note:
95 *      If the unicast mac address already existed in LUT, it will udpate the status of the entry.
96 *      Otherwise, it will find an empty or asic auto learned entry to write. If all the entries
97 *      with the same hash value can't be replaced, ASIC will return a RT_ERR_L2_INDEXTBL_FULL error.
98 */
99rtk_api_ret_t rtk_l2_addr_add(rtk_mac_t *pMac, rtk_l2_ucastAddr_t *pL2_data)
100{
101    rtk_api_ret_t retVal;
102    rtk_uint32 method;
103    rtl8367c_luttb l2Table;
104
105    /* Check initialization state */
106    RTK_CHK_INIT_STATE();
107
108    /* must be unicast address */
109    if ((pMac == NULL) || (pMac->octet[0] & 0x1))
110        return RT_ERR_MAC;
111
112    if(pL2_data == NULL)
113        return RT_ERR_MAC;
114
115    RTK_CHK_PORT_VALID(pL2_data->port);
116
117    if (pL2_data->ivl >= RTK_ENABLE_END)
118        return RT_ERR_INPUT;
119
120    if (pL2_data->cvid > RTL8367C_VIDMAX)
121        return RT_ERR_L2_VID;
122
123    if (pL2_data->fid > RTL8367C_FIDMAX)
124        return RT_ERR_L2_FID;
125
126    if (pL2_data->is_static>= RTK_ENABLE_END)
127        return RT_ERR_INPUT;
128
129    if (pL2_data->sa_block>= RTK_ENABLE_END)
130        return RT_ERR_INPUT;
131
132    if (pL2_data->da_block>= RTK_ENABLE_END)
133        return RT_ERR_INPUT;
134
135    if (pL2_data->auth>= RTK_ENABLE_END)
136        return RT_ERR_INPUT;
137
138    if (pL2_data->efid> RTL8367C_EFIDMAX)
139        return RT_ERR_INPUT;
140
141    if (pL2_data->priority > RTL8367C_PRIMAX)
142        return RT_ERR_INPUT;
143
144    if (pL2_data->sa_pri_en >= RTK_ENABLE_END)
145        return RT_ERR_INPUT;
146
147    if (pL2_data->fwd_pri_en >= RTK_ENABLE_END)
148        return RT_ERR_INPUT;
149
150    memset(&l2Table, 0, sizeof(rtl8367c_luttb));
151
152    /* fill key (MAC,FID) to get L2 entry */
153    memcpy(l2Table.mac.octet, pMac->octet, ETHER_ADDR_LEN);
154    l2Table.ivl_svl     = pL2_data->ivl;
155    l2Table.fid         = pL2_data->fid;
156    l2Table.cvid_fid    = pL2_data->cvid;
157    l2Table.efid        = pL2_data->efid;
158    method = LUTREADMETHOD_MAC;
159    retVal = rtl8367c_getAsicL2LookupTb(method, &l2Table);
160    if (RT_ERR_OK == retVal )
161    {
162        memcpy(l2Table.mac.octet, pMac->octet, ETHER_ADDR_LEN);
163        l2Table.ivl_svl     = pL2_data->ivl;
164        l2Table.cvid_fid    = pL2_data->cvid;
165        l2Table.fid         = pL2_data->fid;
166        l2Table.efid        = pL2_data->efid;
167        l2Table.spa         = rtk_switch_port_L2P_get(pL2_data->port);
168        l2Table.nosalearn   = pL2_data->is_static;
169        l2Table.sa_block    = pL2_data->sa_block;
170        l2Table.da_block    = pL2_data->da_block;
171        l2Table.l3lookup    = 0;
172        l2Table.auth        = pL2_data->auth;
173        l2Table.age         = 6;
174        l2Table.lut_pri     = pL2_data->priority;
175        l2Table.sa_en       = pL2_data->sa_pri_en;
176        l2Table.fwd_en      = pL2_data->fwd_pri_en;
177        if((retVal = rtl8367c_setAsicL2LookupTb(&l2Table)) != RT_ERR_OK)
178            return retVal;
179
180        pL2_data->address = l2Table.address;
181        return RT_ERR_OK;
182    }
183    else if (RT_ERR_L2_ENTRY_NOTFOUND == retVal )
184    {
185        memset(&l2Table, 0, sizeof(rtl8367c_luttb));
186        memcpy(l2Table.mac.octet, pMac->octet, ETHER_ADDR_LEN);
187        l2Table.ivl_svl     = pL2_data->ivl;
188        l2Table.cvid_fid    = pL2_data->cvid;
189        l2Table.fid         = pL2_data->fid;
190        l2Table.efid        = pL2_data->efid;
191        l2Table.spa         = rtk_switch_port_L2P_get(pL2_data->port);
192        l2Table.nosalearn   = pL2_data->is_static;
193        l2Table.sa_block    = pL2_data->sa_block;
194        l2Table.da_block    = pL2_data->da_block;
195        l2Table.l3lookup    = 0;
196        l2Table.auth        = pL2_data->auth;
197        l2Table.age         = 6;
198        l2Table.lut_pri     = pL2_data->priority;
199        l2Table.sa_en       = pL2_data->sa_pri_en;
200        l2Table.fwd_en      = pL2_data->fwd_pri_en;
201
202        if ((retVal = rtl8367c_setAsicL2LookupTb(&l2Table)) != RT_ERR_OK)
203            return retVal;
204
205        pL2_data->address = l2Table.address;
206
207        method = LUTREADMETHOD_MAC;
208        retVal = rtl8367c_getAsicL2LookupTb(method, &l2Table);
209        if (RT_ERR_L2_ENTRY_NOTFOUND == retVal )
210            return RT_ERR_L2_INDEXTBL_FULL;
211        else
212            return retVal;
213    }
214    else
215        return retVal;
216
217}
218
219/* Function Name:
220 *      rtk_l2_addr_get
221 * Description:
222 *      Get LUT unicast entry.
223 * Input:
224 *      pMac    - 6 bytes unicast(I/G bit is 0) mac address to be written into LUT.
225 * Output:
226 *      pL2_data - Unicast entry parameter
227 * Return:
228 *      RT_ERR_OK                   - OK
229 *      RT_ERR_FAILED               - Failed
230 *      RT_ERR_SMI                  - SMI access error
231 *      RT_ERR_PORT_ID              - Invalid port number.
232 *      RT_ERR_MAC                  - Invalid MAC address.
233 *      RT_ERR_L2_FID               - Invalid FID .
234 *      RT_ERR_L2_ENTRY_NOTFOUND    - No such LUT entry.
235 *      RT_ERR_INPUT                - Invalid input parameters.
236 * Note:
237 *      If the unicast mac address existed in LUT, it will return the port and fid where
238 *      the mac is learned. Otherwise, it will return a RT_ERR_L2_ENTRY_NOTFOUND error.
239 */
240rtk_api_ret_t rtk_l2_addr_get(rtk_mac_t *pMac, rtk_l2_ucastAddr_t *pL2_data)
241{
242    rtk_api_ret_t retVal;
243    rtk_uint32 method;
244    rtl8367c_luttb l2Table;
245
246    /* Check initialization state */
247    RTK_CHK_INIT_STATE();
248
249    /* must be unicast address */
250    if ((pMac == NULL) || (pMac->octet[0] & 0x1))
251        return RT_ERR_MAC;
252
253    if (pL2_data->fid > RTL8367C_FIDMAX || pL2_data->efid > RTL8367C_EFIDMAX)
254        return RT_ERR_L2_FID;
255
256    memset(&l2Table, 0, sizeof(rtl8367c_luttb));
257
258    memcpy(l2Table.mac.octet, pMac->octet, ETHER_ADDR_LEN);
259    l2Table.ivl_svl     = pL2_data->ivl;
260    l2Table.cvid_fid    = pL2_data->cvid;
261    l2Table.fid         = pL2_data->fid;
262    l2Table.efid        = pL2_data->efid;
263    method = LUTREADMETHOD_MAC;
264
265    if ((retVal = rtl8367c_getAsicL2LookupTb(method, &l2Table)) != RT_ERR_OK)
266        return retVal;
267
268    memcpy(pL2_data->mac.octet, pMac->octet,ETHER_ADDR_LEN);
269    pL2_data->port      = rtk_switch_port_P2L_get(l2Table.spa);
270    pL2_data->fid       = l2Table.fid;
271    pL2_data->efid      = l2Table.efid;
272    pL2_data->ivl       = l2Table.ivl_svl;
273    pL2_data->cvid      = l2Table.cvid_fid;
274    pL2_data->is_static = l2Table.nosalearn;
275    pL2_data->auth      = l2Table.auth;
276    pL2_data->sa_block  = l2Table.sa_block;
277    pL2_data->da_block  = l2Table.da_block;
278    pL2_data->priority  = l2Table.lut_pri;
279    pL2_data->sa_pri_en = l2Table.sa_en;
280    pL2_data->fwd_pri_en= l2Table.fwd_en;
281    pL2_data->address   = l2Table.address;
282
283    return RT_ERR_OK;
284}
285
286/* Function Name:
287 *      rtk_l2_addr_next_get
288 * Description:
289 *      Get Next LUT unicast entry.
290 * Input:
291 *      read_method     - The reading method.
292 *      port            - The port number if the read_metohd is READMETHOD_NEXT_L2UCSPA
293 *      pAddress        - The Address ID
294 * Output:
295 *      pL2_data - Unicast entry parameter
296 * Return:
297 *      RT_ERR_OK                   - OK
298 *      RT_ERR_FAILED               - Failed
299 *      RT_ERR_SMI                  - SMI access error
300 *      RT_ERR_PORT_ID              - Invalid port number.
301 *      RT_ERR_MAC                  - Invalid MAC address.
302 *      RT_ERR_L2_FID               - Invalid FID .
303 *      RT_ERR_L2_ENTRY_NOTFOUND    - No such LUT entry.
304 *      RT_ERR_INPUT                - Invalid input parameters.
305 * Note:
306 *      Get the next unicast entry after the current entry pointed by pAddress.
307 *      The address of next entry is returned by pAddress. User can use (address + 1)
308 *      as pAddress to call this API again for dumping all entries is LUT.
309 */
310rtk_api_ret_t rtk_l2_addr_next_get(rtk_l2_read_method_t read_method, rtk_port_t port, rtk_uint32 *pAddress, rtk_l2_ucastAddr_t *pL2_data)
311{
312    rtk_api_ret_t   retVal;
313    rtk_uint32      method;
314    rtl8367c_luttb  l2Table;
315
316    /* Check initialization state */
317    RTK_CHK_INIT_STATE();
318
319    /* Error Checking */
320    if ((pL2_data == NULL) || (pAddress == NULL))
321        return RT_ERR_MAC;
322
323    if(read_method == READMETHOD_NEXT_L2UC)
324        method = LUTREADMETHOD_NEXT_L2UC;
325    else if(read_method == READMETHOD_NEXT_L2UCSPA)
326        method = LUTREADMETHOD_NEXT_L2UCSPA;
327    else
328        return RT_ERR_INPUT;
329
330    /* Check Port Valid */
331    RTK_CHK_PORT_VALID(port);
332
333    if(*pAddress > RTK_MAX_LUT_ADDR_ID )
334        return RT_ERR_L2_L2UNI_PARAM;
335
336    memset(&l2Table, 0, sizeof(rtl8367c_luttb));
337    l2Table.address = *pAddress;
338
339    if(read_method == READMETHOD_NEXT_L2UCSPA)
340        l2Table.spa = port;
341
342    if ((retVal = rtl8367c_getAsicL2LookupTb(method, &l2Table)) != RT_ERR_OK)
343        return retVal;
344
345    if(l2Table.address < *pAddress)
346        return RT_ERR_L2_ENTRY_NOTFOUND;
347
348    memcpy(pL2_data->mac.octet, l2Table.mac.octet, ETHER_ADDR_LEN);
349    pL2_data->port      = rtk_switch_port_P2L_get(l2Table.spa);
350    pL2_data->fid       = l2Table.fid;
351    pL2_data->efid      = l2Table.efid;
352    pL2_data->ivl       = l2Table.ivl_svl;
353    pL2_data->cvid      = l2Table.cvid_fid;
354    pL2_data->is_static = l2Table.nosalearn;
355    pL2_data->auth      = l2Table.auth;
356    pL2_data->sa_block  = l2Table.sa_block;
357    pL2_data->da_block  = l2Table.da_block;
358    pL2_data->priority  = l2Table.lut_pri;
359    pL2_data->sa_pri_en = l2Table.sa_en;
360    pL2_data->fwd_pri_en= l2Table.fwd_en;
361    pL2_data->address   = l2Table.address;
362
363    *pAddress = l2Table.address;
364
365    return RT_ERR_OK;
366
367}
368
369/* Function Name:
370 *      rtk_l2_addr_del
371 * Description:
372 *      Delete LUT unicast entry.
373 * Input:
374 *      pMac - 6 bytes unicast(I/G bit is 0) mac address to be written into LUT.
375 *      fid - Filtering database
376 * Output:
377 *      None
378 * Return:
379 *      RT_ERR_OK                   - OK
380 *      RT_ERR_FAILED               - Failed
381 *      RT_ERR_SMI                  - SMI access error
382 *      RT_ERR_PORT_ID              - Invalid port number.
383 *      RT_ERR_MAC                  - Invalid MAC address.
384 *      RT_ERR_L2_FID               - Invalid FID .
385 *      RT_ERR_L2_ENTRY_NOTFOUND    - No such LUT entry.
386 *      RT_ERR_INPUT                - Invalid input parameters.
387 * Note:
388 *      If the mac has existed in the LUT, it will be deleted. Otherwise, it will return RT_ERR_L2_ENTRY_NOTFOUND.
389 */
390rtk_api_ret_t rtk_l2_addr_del(rtk_mac_t *pMac, rtk_l2_ucastAddr_t *pL2_data)
391{
392    rtk_api_ret_t retVal;
393    rtk_uint32 method;
394    rtl8367c_luttb l2Table;
395
396    /* Check initialization state */
397    RTK_CHK_INIT_STATE();
398
399    /* must be unicast address */
400    if ((pMac == NULL) || (pMac->octet[0] & 0x1))
401        return RT_ERR_MAC;
402
403    if (pL2_data->fid > RTL8367C_FIDMAX || pL2_data->efid > RTL8367C_EFIDMAX)
404        return RT_ERR_L2_FID;
405
406    memset(&l2Table, 0, sizeof(rtl8367c_luttb));
407
408    /* fill key (MAC,FID) to get L2 entry */
409    memcpy(l2Table.mac.octet, pMac->octet, ETHER_ADDR_LEN);
410    l2Table.ivl_svl     = pL2_data->ivl;
411    l2Table.cvid_fid    = pL2_data->cvid;
412    l2Table.fid         = pL2_data->fid;
413    l2Table.efid        = pL2_data->efid;
414    method = LUTREADMETHOD_MAC;
415    retVal = rtl8367c_getAsicL2LookupTb(method, &l2Table);
416    if (RT_ERR_OK ==  retVal)
417    {
418        memcpy(l2Table.mac.octet, pMac->octet, ETHER_ADDR_LEN);
419        l2Table.ivl_svl     = pL2_data->ivl;
420        l2Table.cvid_fid    = pL2_data->cvid;
421	    l2Table.fid = pL2_data->fid;
422	    l2Table.efid = pL2_data->efid;
423        l2Table.spa = 0;
424        l2Table.nosalearn = 0;
425        l2Table.sa_block = 0;
426        l2Table.da_block = 0;
427        l2Table.auth = 0;
428        l2Table.age = 0;
429        l2Table.lut_pri = 0;
430        l2Table.sa_en = 0;
431        l2Table.fwd_en = 0;
432        if((retVal = rtl8367c_setAsicL2LookupTb(&l2Table)) != RT_ERR_OK)
433            return retVal;
434
435        pL2_data->address = l2Table.address;
436        return RT_ERR_OK;
437    }
438    else
439        return retVal;
440}
441
442/* Function Name:
443 *      rtk_l2_mcastAddr_add
444 * Description:
445 *      Add LUT multicast entry.
446 * Input:
447 *      pMcastAddr  - L2 multicast entry structure
448 * Output:
449 *      None
450 * Return:
451 *      RT_ERR_OK               - OK
452 *      RT_ERR_FAILED           - Failed
453 *      RT_ERR_SMI              - SMI access error
454 *      RT_ERR_PORT_ID          - Invalid port number.
455 *      RT_ERR_MAC              - Invalid MAC address.
456 *      RT_ERR_L2_FID           - Invalid FID .
457 *      RT_ERR_L2_VID           - Invalid VID .
458 *      RT_ERR_L2_INDEXTBL_FULL - hashed index is full of entries.
459 *      RT_ERR_PORT_MASK        - Invalid portmask.
460 *      RT_ERR_INPUT            - Invalid input parameters.
461 * Note:
462 *      If the multicast mac address already existed in the LUT, it will udpate the
463 *      port mask of the entry. Otherwise, it will find an empty or asic auto learned
464 *      entry to write. If all the entries with the same hash value can't be replaced,
465 *      ASIC will return a RT_ERR_L2_INDEXTBL_FULL error.
466 */
467rtk_api_ret_t rtk_l2_mcastAddr_add(rtk_l2_mcastAddr_t *pMcastAddr)
468{
469    rtk_api_ret_t   retVal;
470    rtk_uint32      method;
471    rtl8367c_luttb  l2Table;
472    rtk_uint32      pmask;
473
474    /* Check initialization state */
475    RTK_CHK_INIT_STATE();
476
477    if(NULL == pMcastAddr)
478        return RT_ERR_NULL_POINTER;
479
480    /* must be L2 multicast address */
481    if( (pMcastAddr->mac.octet[0] & 0x01) != 0x01)
482        return RT_ERR_MAC;
483
484    RTK_CHK_PORTMASK_VALID(&pMcastAddr->portmask);
485
486    if(pMcastAddr->ivl == 1)
487    {
488        if (pMcastAddr->vid > RTL8367C_VIDMAX)
489            return RT_ERR_L2_VID;
490    }
491    else if(pMcastAddr->ivl == 0)
492    {
493        if (pMcastAddr->fid > RTL8367C_FIDMAX)
494            return RT_ERR_L2_FID;
495    }
496    else
497        return RT_ERR_INPUT;
498
499    if(pMcastAddr->fwd_pri_en >= RTK_ENABLE_END)
500        return RT_ERR_INPUT;
501
502    if(pMcastAddr->priority > RTL8367C_PRIMAX)
503        return RT_ERR_INPUT;
504
505    /* Get physical port mask */
506    if ((retVal = rtk_switch_portmask_L2P_get(&pMcastAddr->portmask, &pmask)) != RT_ERR_OK)
507        return retVal;
508
509    memset(&l2Table, 0, sizeof(rtl8367c_luttb));
510
511    /* fill key (MAC,FID) to get L2 entry */
512    memcpy(l2Table.mac.octet, pMcastAddr->mac.octet, ETHER_ADDR_LEN);
513    l2Table.ivl_svl     = pMcastAddr->ivl;
514
515    if(pMcastAddr->ivl)
516        l2Table.cvid_fid    = pMcastAddr->vid;
517    else
518        l2Table.cvid_fid    = pMcastAddr->fid;
519
520    method = LUTREADMETHOD_MAC;
521    retVal = rtl8367c_getAsicL2LookupTb(method, &l2Table);
522    if (RT_ERR_OK == retVal)
523    {
524        memcpy(l2Table.mac.octet, pMcastAddr->mac.octet, ETHER_ADDR_LEN);
525        l2Table.ivl_svl     = pMcastAddr->ivl;
526
527        if(pMcastAddr->ivl)
528            l2Table.cvid_fid    = pMcastAddr->vid;
529        else
530            l2Table.cvid_fid    = pMcastAddr->fid;
531
532        l2Table.mbr         = pmask;
533        l2Table.nosalearn   = 1;
534        l2Table.l3lookup    = 0;
535        l2Table.lut_pri     = pMcastAddr->priority;
536        l2Table.fwd_en      = pMcastAddr->fwd_pri_en;
537        if((retVal = rtl8367c_setAsicL2LookupTb(&l2Table)) != RT_ERR_OK)
538            return retVal;
539
540        pMcastAddr->address = l2Table.address;
541        return RT_ERR_OK;
542    }
543    else if (RT_ERR_L2_ENTRY_NOTFOUND == retVal)
544    {
545        memset(&l2Table, 0, sizeof(rtl8367c_luttb));
546        memcpy(l2Table.mac.octet, pMcastAddr->mac.octet, ETHER_ADDR_LEN);
547        l2Table.ivl_svl     = pMcastAddr->ivl;
548        if(pMcastAddr->ivl)
549            l2Table.cvid_fid    = pMcastAddr->vid;
550        else
551            l2Table.cvid_fid    = pMcastAddr->fid;
552
553        l2Table.mbr         = pmask;
554        l2Table.nosalearn   = 1;
555        l2Table.l3lookup    = 0;
556        l2Table.lut_pri     = pMcastAddr->priority;
557        l2Table.fwd_en      = pMcastAddr->fwd_pri_en;
558        if ((retVal = rtl8367c_setAsicL2LookupTb(&l2Table)) != RT_ERR_OK)
559            return retVal;
560
561        pMcastAddr->address = l2Table.address;
562
563        method = LUTREADMETHOD_MAC;
564        retVal = rtl8367c_getAsicL2LookupTb(method, &l2Table);
565        if (RT_ERR_L2_ENTRY_NOTFOUND == retVal)
566            return     RT_ERR_L2_INDEXTBL_FULL;
567        else
568            return retVal;
569    }
570    else
571        return retVal;
572
573}
574
575/* Function Name:
576 *      rtk_l2_mcastAddr_get
577 * Description:
578 *      Get LUT multicast entry.
579 * Input:
580 *      pMcastAddr  - L2 multicast entry structure
581 * Output:
582 *      pMcastAddr  - L2 multicast entry structure
583 * Return:
584 *      RT_ERR_OK                   - OK
585 *      RT_ERR_FAILED               - Failed
586 *      RT_ERR_SMI                  - SMI access error
587 *      RT_ERR_MAC                  - Invalid MAC address.
588 *      RT_ERR_L2_FID               - Invalid FID .
589 *      RT_ERR_L2_VID               - Invalid VID .
590 *      RT_ERR_L2_ENTRY_NOTFOUND    - No such LUT entry.
591 *      RT_ERR_INPUT                - Invalid input parameters.
592 * Note:
593 *      If the multicast mac address existed in the LUT, it will return the port where
594 *      the mac is learned. Otherwise, it will return a RT_ERR_L2_ENTRY_NOTFOUND error.
595 */
596rtk_api_ret_t rtk_l2_mcastAddr_get(rtk_l2_mcastAddr_t *pMcastAddr)
597{
598    rtk_api_ret_t retVal;
599    rtk_uint32 method;
600    rtl8367c_luttb l2Table;
601
602    /* Check initialization state */
603    RTK_CHK_INIT_STATE();
604
605    if(NULL == pMcastAddr)
606        return RT_ERR_NULL_POINTER;
607
608    /* must be L2 multicast address */
609    if( (pMcastAddr->mac.octet[0] & 0x01) != 0x01)
610        return RT_ERR_MAC;
611
612    if(pMcastAddr->ivl == 1)
613    {
614        if (pMcastAddr->vid > RTL8367C_VIDMAX)
615            return RT_ERR_L2_VID;
616    }
617    else if(pMcastAddr->ivl == 0)
618    {
619        if (pMcastAddr->fid > RTL8367C_FIDMAX)
620            return RT_ERR_L2_FID;
621    }
622    else
623        return RT_ERR_INPUT;
624
625    memset(&l2Table, 0, sizeof(rtl8367c_luttb));
626    memcpy(l2Table.mac.octet, pMcastAddr->mac.octet, ETHER_ADDR_LEN);
627    l2Table.ivl_svl     = pMcastAddr->ivl;
628
629    if(pMcastAddr->ivl)
630        l2Table.cvid_fid    = pMcastAddr->vid;
631    else
632        l2Table.cvid_fid    = pMcastAddr->fid;
633
634    method = LUTREADMETHOD_MAC;
635
636    if ((retVal = rtl8367c_getAsicL2LookupTb(method, &l2Table)) != RT_ERR_OK)
637        return retVal;
638
639    pMcastAddr->priority    = l2Table.lut_pri;
640    pMcastAddr->fwd_pri_en  = l2Table.fwd_en;
641    pMcastAddr->igmp_asic   = l2Table.igmp_asic;
642    pMcastAddr->igmp_index  = l2Table.igmpidx;
643    pMcastAddr->address     = l2Table.address;
644
645    /* Get Logical port mask */
646    if ((retVal = rtk_switch_portmask_P2L_get(l2Table.mbr, &pMcastAddr->portmask)) != RT_ERR_OK)
647        return retVal;
648
649    return RT_ERR_OK;
650}
651
652/* Function Name:
653 *      rtk_l2_mcastAddr_next_get
654 * Description:
655 *      Get Next L2 Multicast entry.
656 * Input:
657 *      pAddress        - The Address ID
658 * Output:
659 *      pMcastAddr  - L2 multicast entry structure
660 * Return:
661 *      RT_ERR_OK                   - OK
662 *      RT_ERR_FAILED               - Failed
663 *      RT_ERR_SMI                  - SMI access error
664 *      RT_ERR_L2_ENTRY_NOTFOUND    - No such LUT entry.
665 *      RT_ERR_INPUT                - Invalid input parameters.
666 * Note:
667 *      Get the next L2 multicast entry after the current entry pointed by pAddress.
668 *      The address of next entry is returned by pAddress. User can use (address + 1)
669 *      as pAddress to call this API again for dumping all multicast entries is LUT.
670 */
671rtk_api_ret_t rtk_l2_mcastAddr_next_get(rtk_uint32 *pAddress, rtk_l2_mcastAddr_t *pMcastAddr)
672{
673    rtk_api_ret_t   retVal;
674    rtl8367c_luttb  l2Table;
675
676    /* Check initialization state */
677    RTK_CHK_INIT_STATE();
678
679    /* Error Checking */
680    if ((pAddress == NULL) || (pMcastAddr == NULL))
681        return RT_ERR_INPUT;
682
683    if(*pAddress > RTK_MAX_LUT_ADDR_ID )
684        return RT_ERR_L2_L2UNI_PARAM;
685
686    memset(&l2Table, 0, sizeof(rtl8367c_luttb));
687    l2Table.address = *pAddress;
688
689    if ((retVal = rtl8367c_getAsicL2LookupTb(LUTREADMETHOD_NEXT_L2MC, &l2Table)) != RT_ERR_OK)
690        return retVal;
691
692    if(l2Table.address < *pAddress)
693        return RT_ERR_L2_ENTRY_NOTFOUND;
694
695    memcpy(pMcastAddr->mac.octet, l2Table.mac.octet, ETHER_ADDR_LEN);
696    pMcastAddr->ivl     = l2Table.ivl_svl;
697
698    if(pMcastAddr->ivl)
699        pMcastAddr->vid = l2Table.cvid_fid;
700    else
701        pMcastAddr->fid = l2Table.cvid_fid;
702
703    pMcastAddr->priority    = l2Table.lut_pri;
704    pMcastAddr->fwd_pri_en  = l2Table.fwd_en;
705    pMcastAddr->igmp_asic   = l2Table.igmp_asic;
706    pMcastAddr->igmp_index  = l2Table.igmpidx;
707    pMcastAddr->address     = l2Table.address;
708
709    /* Get Logical port mask */
710    if ((retVal = rtk_switch_portmask_P2L_get(l2Table.mbr, &pMcastAddr->portmask)) != RT_ERR_OK)
711        return retVal;
712
713    *pAddress = l2Table.address;
714
715    return RT_ERR_OK;
716}
717
718/* Function Name:
719 *      rtk_l2_mcastAddr_del
720 * Description:
721 *      Delete LUT multicast entry.
722 * Input:
723 *      pMcastAddr  - L2 multicast entry structure
724 * Output:
725 *      None
726 * Return:
727 *      RT_ERR_OK                   - OK
728 *      RT_ERR_FAILED               - Failed
729 *      RT_ERR_SMI                  - SMI access error
730 *      RT_ERR_MAC                  - Invalid MAC address.
731 *      RT_ERR_L2_FID               - Invalid FID .
732 *      RT_ERR_L2_VID               - Invalid VID .
733 *      RT_ERR_L2_ENTRY_NOTFOUND    - No such LUT entry.
734 *      RT_ERR_INPUT                - Invalid input parameters.
735 * Note:
736 *      If the mac has existed in the LUT, it will be deleted. Otherwise, it will return RT_ERR_L2_ENTRY_NOTFOUND.
737 */
738rtk_api_ret_t rtk_l2_mcastAddr_del(rtk_l2_mcastAddr_t *pMcastAddr)
739{
740    rtk_api_ret_t retVal;
741    rtk_uint32 method;
742    rtl8367c_luttb l2Table;
743
744    /* Check initialization state */
745    RTK_CHK_INIT_STATE();
746
747    if(NULL == pMcastAddr)
748        return RT_ERR_NULL_POINTER;
749
750    /* must be L2 multicast address */
751    if( (pMcastAddr->mac.octet[0] & 0x01) != 0x01)
752        return RT_ERR_MAC;
753
754    if(pMcastAddr->ivl == 1)
755    {
756        if (pMcastAddr->vid > RTL8367C_VIDMAX)
757            return RT_ERR_L2_VID;
758    }
759    else if(pMcastAddr->ivl == 0)
760    {
761        if (pMcastAddr->fid > RTL8367C_FIDMAX)
762            return RT_ERR_L2_FID;
763    }
764    else
765        return RT_ERR_INPUT;
766
767    memset(&l2Table, 0, sizeof(rtl8367c_luttb));
768
769    /* fill key (MAC,FID) to get L2 entry */
770    memcpy(l2Table.mac.octet, pMcastAddr->mac.octet, ETHER_ADDR_LEN);
771    l2Table.ivl_svl     = pMcastAddr->ivl;
772
773    if(pMcastAddr->ivl)
774        l2Table.cvid_fid    = pMcastAddr->vid;
775    else
776        l2Table.cvid_fid    = pMcastAddr->fid;
777
778    method = LUTREADMETHOD_MAC;
779    retVal = rtl8367c_getAsicL2LookupTb(method, &l2Table);
780    if (RT_ERR_OK == retVal)
781    {
782        memcpy(l2Table.mac.octet, pMcastAddr->mac.octet, ETHER_ADDR_LEN);
783        l2Table.ivl_svl     = pMcastAddr->ivl;
784
785        if(pMcastAddr->ivl)
786            l2Table.cvid_fid    = pMcastAddr->vid;
787        else
788            l2Table.cvid_fid    = pMcastAddr->fid;
789
790        l2Table.mbr         = 0;
791        l2Table.nosalearn   = 0;
792        l2Table.sa_block    = 0;
793        l2Table.l3lookup    = 0;
794        l2Table.lut_pri     = 0;
795        l2Table.fwd_en      = 0;
796        if((retVal = rtl8367c_setAsicL2LookupTb(&l2Table)) != RT_ERR_OK)
797            return retVal;
798
799        pMcastAddr->address = l2Table.address;
800        return RT_ERR_OK;
801    }
802    else
803        return retVal;
804}
805
806/* Function Name:
807 *      rtk_l2_ipMcastAddr_add
808 * Description:
809 *      Add Lut IP multicast entry
810 * Input:
811 *      pIpMcastAddr    - IP Multicast entry
812 * Output:
813 *      None
814 * Return:
815 *      RT_ERR_OK               - OK
816 *      RT_ERR_FAILED           - Failed
817 *      RT_ERR_SMI              - SMI access error
818 *      RT_ERR_PORT_ID          - Invalid port number.
819 *      RT_ERR_L2_INDEXTBL_FULL - hashed index is full of entries.
820 *      RT_ERR_PORT_MASK        - Invalid portmask.
821 *      RT_ERR_INPUT            - Invalid input parameters.
822 * Note:
823 *      System supports L2 entry with IP multicast DIP/SIP to forward IP multicasting frame as user
824 *      desired. If this function is enabled, then system will be looked up L2 IP multicast entry to
825 *      forward IP multicast frame directly without flooding.
826 */
827rtk_api_ret_t rtk_l2_ipMcastAddr_add(rtk_l2_ipMcastAddr_t *pIpMcastAddr)
828{
829    rtk_api_ret_t retVal;
830    rtk_uint32 method;
831    rtl8367c_luttb l2Table;
832    rtk_uint32 pmask;
833
834    /* Check initialization state */
835    RTK_CHK_INIT_STATE();
836
837    if(NULL == pIpMcastAddr)
838        return RT_ERR_NULL_POINTER;
839
840    /* check port mask */
841    RTK_CHK_PORTMASK_VALID(&pIpMcastAddr->portmask);
842
843    if( (pIpMcastAddr->dip & 0xF0000000) != 0xE0000000)
844        return RT_ERR_INPUT;
845
846    if(pIpMcastAddr->fwd_pri_en >= RTK_ENABLE_END)
847        return RT_ERR_ENABLE;
848
849    if(pIpMcastAddr->priority > RTL8367C_PRIMAX)
850        return RT_ERR_INPUT;
851
852    /* Get Physical port mask */
853    if ((retVal = rtk_switch_portmask_L2P_get(&pIpMcastAddr->portmask, &pmask)) != RT_ERR_OK)
854        return retVal;
855
856    memset(&l2Table, 0x00, sizeof(rtl8367c_luttb));
857    l2Table.sip = pIpMcastAddr->sip;
858    l2Table.dip = pIpMcastAddr->dip;
859    l2Table.l3lookup = 1;
860    l2Table.l3vidlookup = 0;
861    method = LUTREADMETHOD_MAC;
862    retVal = rtl8367c_getAsicL2LookupTb(method, &l2Table);
863    if (RT_ERR_OK == retVal)
864    {
865        l2Table.sip = pIpMcastAddr->sip;
866        l2Table.dip = pIpMcastAddr->dip;
867        l2Table.mbr = pmask;
868        l2Table.nosalearn = 1;
869        l2Table.l3lookup = 1;
870        l2Table.l3vidlookup = 0;
871        l2Table.lut_pri = pIpMcastAddr->priority;
872        l2Table.fwd_en  = pIpMcastAddr->fwd_pri_en;
873        if((retVal = rtl8367c_setAsicL2LookupTb(&l2Table)) != RT_ERR_OK)
874            return retVal;
875
876        pIpMcastAddr->address = l2Table.address;
877        return RT_ERR_OK;
878    }
879    else if (RT_ERR_L2_ENTRY_NOTFOUND == retVal)
880    {
881        memset(&l2Table, 0, sizeof(rtl8367c_luttb));
882        l2Table.sip = pIpMcastAddr->sip;
883        l2Table.dip = pIpMcastAddr->dip;
884        l2Table.mbr = pmask;
885        l2Table.nosalearn = 1;
886        l2Table.l3lookup = 1;
887        l2Table.l3vidlookup = 0;
888        l2Table.lut_pri = pIpMcastAddr->priority;
889        l2Table.fwd_en  = pIpMcastAddr->fwd_pri_en;
890        if ((retVal = rtl8367c_setAsicL2LookupTb(&l2Table)) != RT_ERR_OK)
891            return retVal;
892
893        pIpMcastAddr->address = l2Table.address;
894
895        method = LUTREADMETHOD_MAC;
896        retVal = rtl8367c_getAsicL2LookupTb(method, &l2Table);
897        if (RT_ERR_L2_ENTRY_NOTFOUND == retVal)
898            return     RT_ERR_L2_INDEXTBL_FULL;
899        else
900            return retVal;
901
902    }
903    else
904        return retVal;
905
906}
907
908/* Function Name:
909 *      rtk_l2_ipMcastAddr_get
910 * Description:
911 *      Get LUT IP multicast entry.
912 * Input:
913 *      pIpMcastAddr    - IP Multicast entry
914 * Output:
915 *      pIpMcastAddr    - IP Multicast entry
916 * Return:
917 *      RT_ERR_OK                   - OK
918 *      RT_ERR_FAILED               - Failed
919 *      RT_ERR_SMI                  - SMI access error
920 *      RT_ERR_L2_ENTRY_NOTFOUND    - No such LUT entry.
921 *      RT_ERR_INPUT                - Invalid input parameters.
922 * Note:
923 *      The API can get Lut table of IP multicast entry.
924 */
925rtk_api_ret_t rtk_l2_ipMcastAddr_get(rtk_l2_ipMcastAddr_t *pIpMcastAddr)
926{
927    rtk_api_ret_t retVal;
928    rtk_uint32 method;
929    rtl8367c_luttb l2Table;
930
931    /* Check initialization state */
932    RTK_CHK_INIT_STATE();
933
934    if(NULL == pIpMcastAddr)
935        return RT_ERR_NULL_POINTER;
936
937    if( (pIpMcastAddr->dip & 0xF0000000) != 0xE0000000)
938        return RT_ERR_INPUT;
939
940    memset(&l2Table, 0x00, sizeof(rtl8367c_luttb));
941    l2Table.sip = pIpMcastAddr->sip;
942    l2Table.dip = pIpMcastAddr->dip;
943    l2Table.l3lookup = 1;
944    l2Table.l3vidlookup = 0;
945    method = LUTREADMETHOD_MAC;
946    if ((retVal = rtl8367c_getAsicL2LookupTb(method, &l2Table)) != RT_ERR_OK)
947        return retVal;
948
949    /* Get Logical port mask */
950    if ((retVal = rtk_switch_portmask_P2L_get(l2Table.mbr, &pIpMcastAddr->portmask)) != RT_ERR_OK)
951        return retVal;
952
953    pIpMcastAddr->priority      = l2Table.lut_pri;
954    pIpMcastAddr->fwd_pri_en    = l2Table.fwd_en;
955    pIpMcastAddr->igmp_asic     = l2Table.igmp_asic;
956    pIpMcastAddr->igmp_index    = l2Table.igmpidx;
957    pIpMcastAddr->address       = l2Table.address;
958
959    return RT_ERR_OK;
960}
961
962/* Function Name:
963 *      rtk_l2_ipMcastAddr_next_get
964 * Description:
965 *      Get Next IP Multicast entry.
966 * Input:
967 *      pAddress        - The Address ID
968 * Output:
969 *      pIpMcastAddr    - IP Multicast entry
970 * Return:
971 *      RT_ERR_OK                   - OK
972 *      RT_ERR_FAILED               - Failed
973 *      RT_ERR_SMI                  - SMI access error
974 *      RT_ERR_L2_ENTRY_NOTFOUND    - No such LUT entry.
975 *      RT_ERR_INPUT                - Invalid input parameters.
976 * Note:
977 *      Get the next IP multicast entry after the current entry pointed by pAddress.
978 *      The address of next entry is returned by pAddress. User can use (address + 1)
979 *      as pAddress to call this API again for dumping all IP multicast entries is LUT.
980 */
981rtk_api_ret_t rtk_l2_ipMcastAddr_next_get(rtk_uint32 *pAddress, rtk_l2_ipMcastAddr_t *pIpMcastAddr)
982{
983    rtk_api_ret_t   retVal;
984    rtl8367c_luttb  l2Table;
985
986    /* Check initialization state */
987    RTK_CHK_INIT_STATE();
988
989    /* Error Checking */
990    if ((pAddress == NULL) || (pIpMcastAddr == NULL) )
991        return RT_ERR_INPUT;
992
993    if(*pAddress > RTK_MAX_LUT_ADDR_ID )
994        return RT_ERR_L2_L2UNI_PARAM;
995
996    memset(&l2Table, 0, sizeof(rtl8367c_luttb));
997    l2Table.address = *pAddress;
998
999    do
1000    {
1001        if ((retVal = rtl8367c_getAsicL2LookupTb(LUTREADMETHOD_NEXT_L3MC, &l2Table)) != RT_ERR_OK)
1002            return retVal;
1003
1004        if(l2Table.address < *pAddress)
1005            return RT_ERR_L2_ENTRY_NOTFOUND;
1006
1007    }while(l2Table.l3vidlookup == 1);
1008
1009    pIpMcastAddr->sip = l2Table.sip;
1010    pIpMcastAddr->dip = l2Table.dip;
1011
1012    /* Get Logical port mask */
1013    if ((retVal = rtk_switch_portmask_P2L_get(l2Table.mbr, &pIpMcastAddr->portmask)) != RT_ERR_OK)
1014        return retVal;
1015
1016    pIpMcastAddr->priority      = l2Table.lut_pri;
1017    pIpMcastAddr->fwd_pri_en    = l2Table.fwd_en;
1018    pIpMcastAddr->igmp_asic     = l2Table.igmp_asic;
1019    pIpMcastAddr->igmp_index    = l2Table.igmpidx;
1020    pIpMcastAddr->address       = l2Table.address;
1021    *pAddress = l2Table.address;
1022
1023    return RT_ERR_OK;
1024}
1025
1026/* Function Name:
1027 *      rtk_l2_ipMcastAddr_del
1028 * Description:
1029 *      Delete a ip multicast address entry from the specified device.
1030 * Input:
1031 *      pIpMcastAddr    - IP Multicast entry
1032 * Output:
1033 *      None
1034 * Return:
1035 *      RT_ERR_OK                   - OK
1036 *      RT_ERR_FAILED               - Failed
1037 *      RT_ERR_SMI                  - SMI access error
1038 *      RT_ERR_L2_ENTRY_NOTFOUND    - No such LUT entry.
1039 *      RT_ERR_INPUT                - Invalid input parameters.
1040 * Note:
1041 *      The API can delete a IP multicast address entry from the specified device.
1042 */
1043rtk_api_ret_t rtk_l2_ipMcastAddr_del(rtk_l2_ipMcastAddr_t *pIpMcastAddr)
1044{
1045    rtk_api_ret_t retVal;
1046    rtk_uint32 method;
1047    rtl8367c_luttb l2Table;
1048
1049    /* Check initialization state */
1050    RTK_CHK_INIT_STATE();
1051
1052    /* Error Checking */
1053    if (pIpMcastAddr == NULL)
1054        return RT_ERR_INPUT;
1055
1056    if( (pIpMcastAddr->dip & 0xF0000000) != 0xE0000000)
1057        return RT_ERR_INPUT;
1058
1059    memset(&l2Table, 0x00, sizeof(rtl8367c_luttb));
1060    l2Table.sip = pIpMcastAddr->sip;
1061    l2Table.dip = pIpMcastAddr->dip;
1062    l2Table.l3lookup = 1;
1063    l2Table.l3vidlookup = 0;
1064    method = LUTREADMETHOD_MAC;
1065    retVal = rtl8367c_getAsicL2LookupTb(method, &l2Table);
1066    if (RT_ERR_OK == retVal)
1067    {
1068        l2Table.sip = pIpMcastAddr->sip;
1069        l2Table.dip = pIpMcastAddr->dip;
1070        l2Table.mbr = 0;
1071        l2Table.nosalearn = 0;
1072        l2Table.l3lookup = 1;
1073        l2Table.l3vidlookup = 0;
1074        l2Table.lut_pri = 0;
1075        l2Table.fwd_en  = 0;
1076        if((retVal = rtl8367c_setAsicL2LookupTb(&l2Table)) != RT_ERR_OK)
1077            return retVal;
1078
1079        pIpMcastAddr->address = l2Table.address;
1080        return RT_ERR_OK;
1081    }
1082    else
1083        return retVal;
1084}
1085
1086/* Function Name:
1087 *      rtk_l2_ipVidMcastAddr_add
1088 * Description:
1089 *      Add Lut IP multicast+VID entry
1090 * Input:
1091 *      pIpVidMcastAddr - IP & VID multicast Entry
1092 * Output:
1093 *      None
1094 * Return:
1095 *      RT_ERR_OK               - OK
1096 *      RT_ERR_FAILED           - Failed
1097 *      RT_ERR_SMI              - SMI access error
1098 *      RT_ERR_PORT_ID          - Invalid port number.
1099 *      RT_ERR_L2_INDEXTBL_FULL - hashed index is full of entries.
1100 *      RT_ERR_PORT_MASK        - Invalid portmask.
1101 *      RT_ERR_INPUT            - Invalid input parameters.
1102 * Note:
1103 *
1104 */
1105rtk_api_ret_t rtk_l2_ipVidMcastAddr_add(rtk_l2_ipVidMcastAddr_t *pIpVidMcastAddr)
1106{
1107    rtk_api_ret_t retVal;
1108    rtk_uint32 method;
1109    rtl8367c_luttb l2Table;
1110    rtk_uint32 pmask;
1111
1112    /* Check initialization state */
1113    RTK_CHK_INIT_STATE();
1114
1115    if(NULL == pIpVidMcastAddr)
1116        return RT_ERR_NULL_POINTER;
1117
1118    /* check port mask */
1119    RTK_CHK_PORTMASK_VALID(&pIpVidMcastAddr->portmask);
1120
1121    if (pIpVidMcastAddr->vid > RTL8367C_VIDMAX)
1122        return RT_ERR_L2_VID;
1123
1124    if( (pIpVidMcastAddr->dip & 0xF0000000) != 0xE0000000)
1125        return RT_ERR_INPUT;
1126
1127    /* Get Physical port mask */
1128    if ((retVal = rtk_switch_portmask_L2P_get(&pIpVidMcastAddr->portmask, &pmask)) != RT_ERR_OK)
1129        return retVal;
1130
1131    memset(&l2Table, 0x00, sizeof(rtl8367c_luttb));
1132    l2Table.sip = pIpVidMcastAddr->sip;
1133    l2Table.dip = pIpVidMcastAddr->dip;
1134    l2Table.l3lookup = 1;
1135    l2Table.l3vidlookup = 1;
1136    l2Table.l3_vid = pIpVidMcastAddr->vid;
1137    method = LUTREADMETHOD_MAC;
1138    retVal = rtl8367c_getAsicL2LookupTb(method, &l2Table);
1139    if (RT_ERR_OK == retVal)
1140    {
1141        l2Table.sip = pIpVidMcastAddr->sip;
1142        l2Table.dip = pIpVidMcastAddr->dip;
1143        l2Table.mbr = pmask;
1144        l2Table.nosalearn = 1;
1145        l2Table.l3lookup = 1;
1146        l2Table.l3vidlookup = 1;
1147        l2Table.l3_vid = pIpVidMcastAddr->vid;
1148        if((retVal = rtl8367c_setAsicL2LookupTb(&l2Table)) != RT_ERR_OK)
1149            return retVal;
1150
1151        pIpVidMcastAddr->address = l2Table.address;
1152        return RT_ERR_OK;
1153    }
1154    else if (RT_ERR_L2_ENTRY_NOTFOUND == retVal)
1155    {
1156        memset(&l2Table, 0, sizeof(rtl8367c_luttb));
1157        l2Table.sip = pIpVidMcastAddr->sip;
1158        l2Table.dip = pIpVidMcastAddr->dip;
1159        l2Table.mbr = pmask;
1160        l2Table.nosalearn = 1;
1161        l2Table.l3lookup = 1;
1162        l2Table.l3vidlookup = 1;
1163        l2Table.l3_vid = pIpVidMcastAddr->vid;
1164        if ((retVal = rtl8367c_setAsicL2LookupTb(&l2Table)) != RT_ERR_OK)
1165            return retVal;
1166
1167        pIpVidMcastAddr->address = l2Table.address;
1168
1169        method = LUTREADMETHOD_MAC;
1170        retVal = rtl8367c_getAsicL2LookupTb(method, &l2Table);
1171        if (RT_ERR_L2_ENTRY_NOTFOUND == retVal)
1172            return     RT_ERR_L2_INDEXTBL_FULL;
1173        else
1174            return retVal;
1175
1176    }
1177    else
1178        return retVal;
1179}
1180
1181/* Function Name:
1182 *      rtk_l2_ipVidMcastAddr_get
1183 * Description:
1184 *      Get LUT IP multicast+VID entry.
1185 * Input:
1186 *      pIpVidMcastAddr - IP & VID multicast Entry
1187 * Output:
1188 *      pIpVidMcastAddr - IP & VID multicast Entry
1189 * Return:
1190 *      RT_ERR_OK                   - OK
1191 *      RT_ERR_FAILED               - Failed
1192 *      RT_ERR_SMI                  - SMI access error
1193 *      RT_ERR_L2_ENTRY_NOTFOUND    - No such LUT entry.
1194 *      RT_ERR_INPUT                - Invalid input parameters.
1195 * Note:
1196 *
1197 */
1198rtk_api_ret_t rtk_l2_ipVidMcastAddr_get(rtk_l2_ipVidMcastAddr_t *pIpVidMcastAddr)
1199{
1200    rtk_api_ret_t retVal;
1201    rtk_uint32 method;
1202    rtl8367c_luttb l2Table;
1203
1204    /* Check initialization state */
1205    RTK_CHK_INIT_STATE();
1206
1207    if(NULL == pIpVidMcastAddr)
1208        return RT_ERR_NULL_POINTER;
1209
1210    if (pIpVidMcastAddr->vid > RTL8367C_VIDMAX)
1211        return RT_ERR_L2_VID;
1212
1213    if( (pIpVidMcastAddr->dip & 0xF0000000) != 0xE0000000)
1214        return RT_ERR_INPUT;
1215
1216    memset(&l2Table, 0x00, sizeof(rtl8367c_luttb));
1217    l2Table.sip = pIpVidMcastAddr->sip;
1218    l2Table.dip = pIpVidMcastAddr->dip;
1219    l2Table.l3lookup = 1;
1220    l2Table.l3vidlookup = 1;
1221    l2Table.l3_vid = pIpVidMcastAddr->vid;
1222    method = LUTREADMETHOD_MAC;
1223    if ((retVal = rtl8367c_getAsicL2LookupTb(method, &l2Table)) != RT_ERR_OK)
1224        return retVal;
1225
1226    pIpVidMcastAddr->address = l2Table.address;
1227
1228     /* Get Logical port mask */
1229    if ((retVal = rtk_switch_portmask_P2L_get(l2Table.mbr, &pIpVidMcastAddr->portmask)) != RT_ERR_OK)
1230        return retVal;
1231
1232    return RT_ERR_OK;
1233}
1234
1235/* Function Name:
1236 *      rtk_l2_ipVidMcastAddr_next_get
1237 * Description:
1238 *      Get Next IP Multicast+VID entry.
1239 * Input:
1240 *      pAddress        - The Address ID
1241 * Output:
1242 *      pIpVidMcastAddr - IP & VID multicast Entry
1243 * Return:
1244 *      RT_ERR_OK                   - OK
1245 *      RT_ERR_FAILED               - Failed
1246 *      RT_ERR_SMI                  - SMI access error
1247 *      RT_ERR_L2_ENTRY_NOTFOUND    - No such LUT entry.
1248 *      RT_ERR_INPUT                - Invalid input parameters.
1249 * Note:
1250 *      Get the next IP multicast entry after the current entry pointed by pAddress.
1251 *      The address of next entry is returned by pAddress. User can use (address + 1)
1252 *      as pAddress to call this API again for dumping all IP multicast entries is LUT.
1253 */
1254rtk_api_ret_t rtk_l2_ipVidMcastAddr_next_get(rtk_uint32 *pAddress, rtk_l2_ipVidMcastAddr_t *pIpVidMcastAddr)
1255{
1256    rtk_api_ret_t   retVal;
1257    rtl8367c_luttb  l2Table;
1258
1259    /* Check initialization state */
1260    RTK_CHK_INIT_STATE();
1261
1262    /* Error Checking */
1263    if ((pAddress == NULL) || (pIpVidMcastAddr == NULL))
1264        return RT_ERR_INPUT;
1265
1266    if(*pAddress > RTK_MAX_LUT_ADDR_ID )
1267        return RT_ERR_L2_L2UNI_PARAM;
1268
1269    memset(&l2Table, 0, sizeof(rtl8367c_luttb));
1270    l2Table.address = *pAddress;
1271
1272    do
1273    {
1274        if ((retVal = rtl8367c_getAsicL2LookupTb(LUTREADMETHOD_NEXT_L3MC, &l2Table)) != RT_ERR_OK)
1275            return retVal;
1276
1277        if(l2Table.address < *pAddress)
1278            return RT_ERR_L2_ENTRY_NOTFOUND;
1279
1280    }while(l2Table.l3vidlookup == 0);
1281
1282    pIpVidMcastAddr->sip        = l2Table.sip;
1283    pIpVidMcastAddr->dip        = l2Table.dip;
1284    pIpVidMcastAddr->vid        = l2Table.l3_vid;
1285    pIpVidMcastAddr->address    = l2Table.address;
1286
1287    /* Get Logical port mask */
1288    if ((retVal = rtk_switch_portmask_P2L_get(l2Table.mbr, &pIpVidMcastAddr->portmask)) != RT_ERR_OK)
1289        return retVal;
1290
1291    *pAddress = l2Table.address;
1292
1293    return RT_ERR_OK;
1294}
1295
1296/* Function Name:
1297 *      rtk_l2_ipVidMcastAddr_del
1298 * Description:
1299 *      Delete a ip multicast+VID address entry from the specified device.
1300 * Input:
1301 *      pIpVidMcastAddr - IP & VID multicast Entry
1302 * Output:
1303 *      None
1304 * Return:
1305 *      RT_ERR_OK                   - OK
1306 *      RT_ERR_FAILED               - Failed
1307 *      RT_ERR_SMI                  - SMI access error
1308 *      RT_ERR_L2_ENTRY_NOTFOUND    - No such LUT entry.
1309 *      RT_ERR_INPUT                - Invalid input parameters.
1310 * Note:
1311 *
1312 */
1313rtk_api_ret_t rtk_l2_ipVidMcastAddr_del(rtk_l2_ipVidMcastAddr_t *pIpVidMcastAddr)
1314{
1315    rtk_api_ret_t retVal;
1316    rtk_uint32 method;
1317    rtl8367c_luttb l2Table;
1318
1319    /* Check initialization state */
1320    RTK_CHK_INIT_STATE();
1321
1322    if(NULL == pIpVidMcastAddr)
1323        return RT_ERR_NULL_POINTER;
1324
1325    if (pIpVidMcastAddr->vid > RTL8367C_VIDMAX)
1326        return RT_ERR_L2_VID;
1327
1328    if( (pIpVidMcastAddr->dip & 0xF0000000) != 0xE0000000)
1329        return RT_ERR_INPUT;
1330
1331    memset(&l2Table, 0x00, sizeof(rtl8367c_luttb));
1332    l2Table.sip = pIpVidMcastAddr->sip;
1333    l2Table.dip = pIpVidMcastAddr->dip;
1334    l2Table.l3lookup = 1;
1335    l2Table.l3vidlookup = 1;
1336    l2Table.l3_vid = pIpVidMcastAddr->vid;
1337    method = LUTREADMETHOD_MAC;
1338    retVal = rtl8367c_getAsicL2LookupTb(method, &l2Table);
1339    if (RT_ERR_OK == retVal)
1340    {
1341        l2Table.sip = pIpVidMcastAddr->sip;
1342        l2Table.dip = pIpVidMcastAddr->dip;
1343        l2Table.mbr= 0;
1344        l2Table.nosalearn = 0;
1345        l2Table.l3lookup = 1;
1346        l2Table.l3vidlookup = 1;
1347        l2Table.l3_vid = pIpVidMcastAddr->vid;
1348        if((retVal = rtl8367c_setAsicL2LookupTb(&l2Table)) != RT_ERR_OK)
1349            return retVal;
1350
1351        pIpVidMcastAddr->address = l2Table.address;
1352        return RT_ERR_OK;
1353    }
1354    else
1355        return retVal;
1356}
1357
1358/* Function Name:
1359 *      rtk_l2_ucastAddr_flush
1360 * Description:
1361 *      Flush L2 mac address by type in the specified device (both dynamic and static).
1362 * Input:
1363 *      pConfig - flush configuration
1364 * Output:
1365 *      None
1366 * Return:
1367 *      RT_ERR_OK           - OK
1368 *      RT_ERR_FAILED       - Failed
1369 *      RT_ERR_SMI          - SMI access error
1370 *      RT_ERR_PORT_ID      - Invalid port number.
1371 *      RT_ERR_VLAN_VID     - Invalid VID parameter.
1372 *      RT_ERR_INPUT        - Invalid input parameters.
1373 * Note:
1374 *      flushByVid          - 1: Flush by VID, 0: Don't flush by VID
1375 *      vid                 - VID (0 ~ 4095)
1376 *      flushByFid          - 1: Flush by FID, 0: Don't flush by FID
1377 *      fid                 - FID (0 ~ 15)
1378 *      flushByPort         - 1: Flush by Port, 0: Don't flush by Port
1379 *      port                - Port ID
1380 *      flushByMac          - Not Supported
1381 *      ucastAddr           - Not Supported
1382 *      flushStaticAddr     - 1: Flush both Static and Dynamic entries, 0: Flush only Dynamic entries
1383 *      flushAddrOnAllPorts - 1: Flush VID-matched entries at all ports, 0: Flush VID-matched entries per port.
1384 */
1385rtk_api_ret_t rtk_l2_ucastAddr_flush(rtk_l2_flushCfg_t *pConfig)
1386{
1387    rtk_api_ret_t   retVal;
1388
1389    /* Check initialization state */
1390    RTK_CHK_INIT_STATE();
1391
1392    if(pConfig == NULL)
1393        return RT_ERR_NULL_POINTER;
1394
1395    if(pConfig->flushByVid >= RTK_ENABLE_END)
1396        return RT_ERR_ENABLE;
1397
1398    if(pConfig->flushByFid >= RTK_ENABLE_END)
1399        return RT_ERR_ENABLE;
1400
1401    if(pConfig->flushByPort >= RTK_ENABLE_END)
1402        return RT_ERR_ENABLE;
1403
1404    if(pConfig->flushByMac >= RTK_ENABLE_END)
1405        return RT_ERR_ENABLE;
1406
1407    if(pConfig->flushStaticAddr >= RTK_ENABLE_END)
1408        return RT_ERR_ENABLE;
1409
1410    if(pConfig->flushAddrOnAllPorts >= RTK_ENABLE_END)
1411        return RT_ERR_ENABLE;
1412
1413    if(pConfig->vid > RTL8367C_VIDMAX)
1414        return RT_ERR_VLAN_VID;
1415
1416    if(pConfig->fid > RTL8367C_FIDMAX)
1417        return RT_ERR_INPUT;
1418
1419    /* check port valid */
1420    RTK_CHK_PORT_VALID(pConfig->port);
1421
1422    if(pConfig->flushByVid == ENABLED)
1423    {
1424        if ((retVal = rtl8367c_setAsicLutFlushMode(FLUSHMDOE_VID)) != RT_ERR_OK)
1425            return retVal;
1426
1427        if ((retVal = rtl8367c_setAsicLutFlushVid(pConfig->vid)) != RT_ERR_OK)
1428                return retVal;
1429
1430        if ((retVal = rtl8367c_setAsicLutFlushType((pConfig->flushStaticAddr == ENABLED) ? FLUSHTYPE_BOTH : FLUSHTYPE_DYNAMIC)) != RT_ERR_OK)
1431            return retVal;
1432
1433        if(pConfig->flushAddrOnAllPorts == ENABLED)
1434        {
1435            if ((retVal = rtl8367c_setAsicLutForceFlush(RTL8367C_PORTMASK)) != RT_ERR_OK)
1436                return retVal;
1437        }
1438        else if(pConfig->flushByPort == ENABLED)
1439        {
1440            if ((retVal = rtl8367c_setAsicLutForceFlush(1 << rtk_switch_port_L2P_get(pConfig->port))) != RT_ERR_OK)
1441                return retVal;
1442        }
1443        else
1444            return RT_ERR_INPUT;
1445    }
1446    else if(pConfig->flushByFid == ENABLED)
1447    {
1448        if ((retVal = rtl8367c_setAsicLutFlushMode(FLUSHMDOE_FID)) != RT_ERR_OK)
1449            return retVal;
1450
1451        if ((retVal = rtl8367c_setAsicLutFlushFid(pConfig->fid)) != RT_ERR_OK)
1452                return retVal;
1453
1454        if ((retVal = rtl8367c_setAsicLutFlushType((pConfig->flushStaticAddr == ENABLED) ? FLUSHTYPE_BOTH : FLUSHTYPE_DYNAMIC)) != RT_ERR_OK)
1455            return retVal;
1456
1457        if(pConfig->flushAddrOnAllPorts == ENABLED)
1458        {
1459            if ((retVal = rtl8367c_setAsicLutForceFlush(RTL8367C_PORTMASK)) != RT_ERR_OK)
1460                return retVal;
1461        }
1462        else if(pConfig->flushByPort == ENABLED)
1463        {
1464            if ((retVal = rtl8367c_setAsicLutForceFlush(1 << rtk_switch_port_L2P_get(pConfig->port))) != RT_ERR_OK)
1465                return retVal;
1466        }
1467        else
1468            return RT_ERR_INPUT;
1469    }
1470    else if(pConfig->flushByPort == ENABLED)
1471    {
1472        if ((retVal = rtl8367c_setAsicLutFlushType((pConfig->flushStaticAddr == ENABLED) ? FLUSHTYPE_BOTH : FLUSHTYPE_DYNAMIC)) != RT_ERR_OK)
1473            return retVal;
1474
1475        if ((retVal = rtl8367c_setAsicLutFlushMode(FLUSHMDOE_PORT)) != RT_ERR_OK)
1476            return retVal;
1477
1478        if ((retVal = rtl8367c_setAsicLutForceFlush(1 << rtk_switch_port_L2P_get(pConfig->port))) != RT_ERR_OK)
1479            return retVal;
1480    }
1481    else if(pConfig->flushByMac == ENABLED)
1482    {
1483        /* Should use API "rtk_l2_addr_del" to remove a specified entry*/
1484        return RT_ERR_CHIP_NOT_SUPPORTED;
1485    }
1486    else
1487        return RT_ERR_INPUT;
1488
1489    return RT_ERR_OK;
1490}
1491
1492/* Function Name:
1493 *      rtk_l2_table_clear
1494 * Description:
1495 *      Flush all static & dynamic entries in LUT.
1496 * Input:
1497 *      None
1498 * Output:
1499 *      None
1500 * Return:
1501 *      RT_ERR_OK           - OK
1502 *      RT_ERR_FAILED       - Failed
1503 *      RT_ERR_SMI          - SMI access error
1504 * Note:
1505 *
1506 */
1507rtk_api_ret_t rtk_l2_table_clear(void)
1508{
1509    rtk_api_ret_t   retVal;
1510
1511    /* Check initialization state */
1512    RTK_CHK_INIT_STATE();
1513
1514    if ((retVal = rtl8367c_setAsicLutFlushAll()) != RT_ERR_OK)
1515        return retVal;
1516
1517    return RT_ERR_OK;
1518}
1519
1520/* Function Name:
1521 *      rtk_l2_table_clearStatus_get
1522 * Description:
1523 *      Get table clear status
1524 * Input:
1525 *      None
1526 * Output:
1527 *      pStatus - Clear status, 1:Busy, 0:finish
1528 * Return:
1529 *      RT_ERR_OK           - OK
1530 *      RT_ERR_FAILED       - Failed
1531 *      RT_ERR_SMI          - SMI access error
1532 * Note:
1533 *
1534 */
1535rtk_api_ret_t rtk_l2_table_clearStatus_get(rtk_l2_clearStatus_t *pStatus)
1536{
1537    rtk_api_ret_t   retVal;
1538
1539    /* Check initialization state */
1540    RTK_CHK_INIT_STATE();
1541
1542    if(NULL == pStatus)
1543        return RT_ERR_NULL_POINTER;
1544
1545    if ((retVal = rtl8367c_getAsicLutFlushAllStatus((rtk_uint32 *)pStatus)) != RT_ERR_OK)
1546        return retVal;
1547
1548    return RT_ERR_OK;
1549}
1550
1551/* Function Name:
1552 *      rtk_l2_flushLinkDownPortAddrEnable_set
1553 * Description:
1554 *      Set HW flush linkdown port mac configuration of the specified device.
1555 * Input:
1556 *      port - Port id.
1557 *      enable - link down flush status
1558 * Output:
1559 *      None
1560 * Return:
1561 *      RT_ERR_OK           - OK
1562 *      RT_ERR_FAILED       - Failed
1563 *      RT_ERR_SMI          - SMI access error
1564 *      RT_ERR_PORT_ID      - Invalid port number.
1565 *      RT_ERR_ENABLE       - Invalid enable input.
1566 * Note:
1567 *      The status of flush linkdown port address is as following:
1568 *      - DISABLED
1569 *      - ENABLED
1570 */
1571rtk_api_ret_t rtk_l2_flushLinkDownPortAddrEnable_set(rtk_port_t port, rtk_enable_t enable)
1572{
1573    rtk_api_ret_t retVal;
1574
1575    /* Check initialization state */
1576    RTK_CHK_INIT_STATE();
1577
1578    if (port != RTK_WHOLE_SYSTEM)
1579        return RT_ERR_PORT_ID;
1580
1581    if (enable >= RTK_ENABLE_END)
1582        return RT_ERR_ENABLE;
1583
1584    if ((retVal = rtl8367c_setAsicLutLinkDownForceAging(enable)) != RT_ERR_OK)
1585        return retVal;
1586
1587
1588    return RT_ERR_OK;
1589}
1590
1591/* Function Name:
1592 *      rtk_l2_flushLinkDownPortAddrEnable_get
1593 * Description:
1594 *      Get HW flush linkdown port mac configuration of the specified device.
1595 * Input:
1596 *      port - Port id.
1597 * Output:
1598 *      pEnable - link down flush status
1599 * Return:
1600 *      RT_ERR_OK           - OK
1601 *      RT_ERR_FAILED       - Failed
1602 *      RT_ERR_SMI          - SMI access error
1603 *      RT_ERR_PORT_ID      - Invalid port number.
1604 * Note:
1605 *      The status of flush linkdown port address is as following:
1606 *      - DISABLED
1607 *      - ENABLED
1608 */
1609rtk_api_ret_t rtk_l2_flushLinkDownPortAddrEnable_get(rtk_port_t port, rtk_enable_t *pEnable)
1610{
1611    rtk_api_ret_t retVal;
1612
1613    /* Check initialization state */
1614    RTK_CHK_INIT_STATE();
1615
1616    if (port != RTK_WHOLE_SYSTEM)
1617        return RT_ERR_PORT_ID;
1618
1619    if(NULL == pEnable)
1620        return RT_ERR_NULL_POINTER;
1621
1622    if ((retVal = rtl8367c_getAsicLutLinkDownForceAging(pEnable)) != RT_ERR_OK)
1623        return retVal;
1624
1625    return RT_ERR_OK;
1626}
1627
1628/* Function Name:
1629 *      rtk_l2_agingEnable_set
1630 * Description:
1631 *      Set L2 LUT aging status per port setting.
1632 * Input:
1633 *      port    - Port id.
1634 *      enable  - Aging status
1635 * Output:
1636 *      None
1637 * Return:
1638 *      RT_ERR_OK           - OK
1639 *      RT_ERR_FAILED       - Failed
1640 *      RT_ERR_SMI          - SMI access error
1641 *      RT_ERR_PORT_ID      - Invalid port number.
1642 *      RT_ERR_ENABLE       - Invalid enable input.
1643 * Note:
1644 *      This API can be used to set L2 LUT aging status per port.
1645 */
1646rtk_api_ret_t rtk_l2_agingEnable_set(rtk_port_t port, rtk_enable_t enable)
1647{
1648    rtk_api_ret_t retVal;
1649
1650    /* Check initialization state */
1651    RTK_CHK_INIT_STATE();
1652
1653    /* check port valid */
1654    RTK_CHK_PORT_VALID(port);
1655
1656    if (enable >= RTK_ENABLE_END)
1657        return RT_ERR_ENABLE;
1658
1659    if(enable == 1)
1660        enable = 0;
1661    else
1662        enable = 1;
1663
1664    if ((retVal = rtl8367c_setAsicLutDisableAging(rtk_switch_port_L2P_get(port), enable)) != RT_ERR_OK)
1665        return retVal;
1666
1667    return RT_ERR_OK;
1668}
1669
1670/* Function Name:
1671 *      rtk_l2_agingEnable_get
1672 * Description:
1673 *      Get L2 LUT aging status per port setting.
1674 * Input:
1675 *      port - Port id.
1676 * Output:
1677 *      pEnable - Aging status
1678 * Return:
1679 *      RT_ERR_OK           - OK
1680 *      RT_ERR_FAILED       - Failed
1681 *      RT_ERR_SMI          - SMI access error
1682 *      RT_ERR_PORT_ID      - Invalid port number.
1683 * Note:
1684 *      This API can be used to get L2 LUT aging function per port.
1685 */
1686rtk_api_ret_t rtk_l2_agingEnable_get(rtk_port_t port, rtk_enable_t *pEnable)
1687{
1688    rtk_api_ret_t retVal;
1689
1690    /* Check initialization state */
1691    RTK_CHK_INIT_STATE();
1692
1693    /* check port valid */
1694    RTK_CHK_PORT_VALID(port);
1695
1696    if(NULL == pEnable)
1697        return RT_ERR_NULL_POINTER;
1698
1699    if ((retVal = rtl8367c_getAsicLutDisableAging(rtk_switch_port_L2P_get(port), pEnable)) != RT_ERR_OK)
1700        return retVal;
1701
1702    if(*pEnable == 1)
1703        *pEnable = 0;
1704    else
1705        *pEnable = 1;
1706
1707    return RT_ERR_OK;
1708}
1709
1710/* Function Name:
1711 *      rtk_l2_limitLearningCnt_set
1712 * Description:
1713 *      Set per-Port auto learning limit number
1714 * Input:
1715 *      port    - Port id.
1716 *      mac_cnt - Auto learning entries limit number
1717 * Output:
1718 *      None
1719 * Return:
1720 *      RT_ERR_OK                   - OK
1721 *      RT_ERR_FAILED               - Failed
1722 *      RT_ERR_SMI                  - SMI access error
1723 *      RT_ERR_PORT_ID              - Invalid port number.
1724 *      RT_ERR_LIMITED_L2ENTRY_NUM  - Invalid auto learning limit number
1725 * Note:
1726 *      The API can set per-port ASIC auto learning limit number from 0(disable learning)
1727 *      to 2112.
1728 */
1729rtk_api_ret_t rtk_l2_limitLearningCnt_set(rtk_port_t port, rtk_mac_cnt_t mac_cnt)
1730{
1731    rtk_api_ret_t retVal;
1732
1733    /* Check initialization state */
1734    RTK_CHK_INIT_STATE();
1735
1736    /* check port valid */
1737    RTK_CHK_PORT_VALID(port);
1738
1739    if (mac_cnt > rtk_switch_maxLutAddrNumber_get())
1740        return RT_ERR_LIMITED_L2ENTRY_NUM;
1741
1742    if ((retVal = rtl8367c_setAsicLutLearnLimitNo(rtk_switch_port_L2P_get(port), mac_cnt)) != RT_ERR_OK)
1743        return retVal;
1744
1745    return RT_ERR_OK;
1746}
1747
1748/* Function Name:
1749 *      rtk_l2_limitLearningCnt_get
1750 * Description:
1751 *      Get per-Port auto learning limit number
1752 * Input:
1753 *      port - Port id.
1754 * Output:
1755 *      pMac_cnt - Auto learning entries limit number
1756 * Return:
1757 *      RT_ERR_OK           - OK
1758 *      RT_ERR_FAILED       - Failed
1759 *      RT_ERR_SMI          - SMI access error
1760 *      RT_ERR_PORT_ID      - Invalid port number.
1761 * Note:
1762 *      The API can get per-port ASIC auto learning limit number.
1763 */
1764rtk_api_ret_t rtk_l2_limitLearningCnt_get(rtk_port_t port, rtk_mac_cnt_t *pMac_cnt)
1765{
1766    rtk_api_ret_t retVal;
1767
1768    /* Check initialization state */
1769    RTK_CHK_INIT_STATE();
1770
1771    /* check port valid */
1772    RTK_CHK_PORT_VALID(port);
1773
1774    if(NULL == pMac_cnt)
1775        return RT_ERR_NULL_POINTER;
1776
1777    if ((retVal = rtl8367c_getAsicLutLearnLimitNo(rtk_switch_port_L2P_get(port), pMac_cnt)) != RT_ERR_OK)
1778        return retVal;
1779
1780    return RT_ERR_OK;
1781}
1782
1783/* Function Name:
1784 *      rtk_l2_limitSystemLearningCnt_set
1785 * Description:
1786 *      Set System auto learning limit number
1787 * Input:
1788 *      mac_cnt - Auto learning entries limit number
1789 * Output:
1790 *      None
1791 * Return:
1792 *      RT_ERR_OK                   - OK
1793 *      RT_ERR_FAILED               - Failed
1794 *      RT_ERR_SMI                  - SMI access error
1795 *      RT_ERR_LIMITED_L2ENTRY_NUM  - Invalid auto learning limit number
1796 * Note:
1797 *      The API can set system ASIC auto learning limit number from 0(disable learning)
1798 *      to 2112.
1799 */
1800rtk_api_ret_t rtk_l2_limitSystemLearningCnt_set(rtk_mac_cnt_t mac_cnt)
1801{
1802    rtk_api_ret_t retVal;
1803
1804    /* Check initialization state */
1805    RTK_CHK_INIT_STATE();
1806
1807    if (mac_cnt > rtk_switch_maxLutAddrNumber_get())
1808        return RT_ERR_LIMITED_L2ENTRY_NUM;
1809
1810    if ((retVal = rtl8367c_setAsicSystemLutLearnLimitNo(mac_cnt)) != RT_ERR_OK)
1811        return retVal;
1812
1813    return RT_ERR_OK;
1814}
1815
1816/* Function Name:
1817 *      rtk_l2_limitSystemLearningCnt_get
1818 * Description:
1819 *      Get System auto learning limit number
1820 * Input:
1821 *      None
1822 * Output:
1823 *      pMac_cnt - Auto learning entries limit number
1824 * Return:
1825 *      RT_ERR_OK           - OK
1826 *      RT_ERR_FAILED       - Failed
1827 *      RT_ERR_SMI          - SMI access error
1828 *      RT_ERR_PORT_ID      - Invalid port number.
1829 * Note:
1830 *      The API can get system ASIC auto learning limit number.
1831 */
1832rtk_api_ret_t rtk_l2_limitSystemLearningCnt_get(rtk_mac_cnt_t *pMac_cnt)
1833{
1834    rtk_api_ret_t retVal;
1835
1836    /* Check initialization state */
1837    RTK_CHK_INIT_STATE();
1838
1839    if(NULL == pMac_cnt)
1840        return RT_ERR_NULL_POINTER;
1841
1842    if ((retVal = rtl8367c_getAsicSystemLutLearnLimitNo(pMac_cnt)) != RT_ERR_OK)
1843        return retVal;
1844
1845    return RT_ERR_OK;
1846}
1847
1848/* Function Name:
1849 *      rtk_l2_limitLearningCntAction_set
1850 * Description:
1851 *      Configure auto learn over limit number action.
1852 * Input:
1853 *      port - Port id.
1854 *      action - Auto learning entries limit number
1855 * Output:
1856 *      None
1857 * Return:
1858 *      RT_ERR_OK           - OK
1859 *      RT_ERR_FAILED       - Failed
1860 *      RT_ERR_SMI          - SMI access error
1861 *      RT_ERR_PORT_ID      - Invalid port number.
1862 *      RT_ERR_NOT_ALLOWED  - Invalid learn over action
1863 * Note:
1864 *      The API can set SA unknown packet action while auto learn limit number is over
1865 *      The action symbol as following:
1866 *      - LIMIT_LEARN_CNT_ACTION_DROP,
1867 *      - LIMIT_LEARN_CNT_ACTION_FORWARD,
1868 *      - LIMIT_LEARN_CNT_ACTION_TO_CPU,
1869 */
1870rtk_api_ret_t rtk_l2_limitLearningCntAction_set(rtk_port_t port, rtk_l2_limitLearnCntAction_t action)
1871{
1872    rtk_api_ret_t retVal;
1873    rtk_uint32 data;
1874
1875    /* Check initialization state */
1876    RTK_CHK_INIT_STATE();
1877
1878    if (port != RTK_WHOLE_SYSTEM)
1879        return RT_ERR_PORT_ID;
1880
1881    if ( LIMIT_LEARN_CNT_ACTION_DROP == action )
1882        data = 1;
1883    else if ( LIMIT_LEARN_CNT_ACTION_FORWARD == action )
1884        data = 0;
1885    else if ( LIMIT_LEARN_CNT_ACTION_TO_CPU == action )
1886        data = 2;
1887    else
1888        return RT_ERR_NOT_ALLOWED;
1889
1890    if ((retVal = rtl8367c_setAsicLutLearnOverAct(data)) != RT_ERR_OK)
1891        return retVal;
1892
1893    return RT_ERR_OK;
1894}
1895
1896/* Function Name:
1897 *      rtk_l2_limitLearningCntAction_get
1898 * Description:
1899 *      Get auto learn over limit number action.
1900 * Input:
1901 *      port - Port id.
1902 * Output:
1903 *      pAction - Learn over action
1904 * Return:
1905 *      RT_ERR_OK           - OK
1906 *      RT_ERR_FAILED       - Failed
1907 *      RT_ERR_SMI          - SMI access error
1908 *      RT_ERR_PORT_ID      - Invalid port number.
1909 * Note:
1910 *      The API can get SA unknown packet action while auto learn limit number is over
1911 *      The action symbol as following:
1912 *      - LIMIT_LEARN_CNT_ACTION_DROP,
1913 *      - LIMIT_LEARN_CNT_ACTION_FORWARD,
1914 *      - LIMIT_LEARN_CNT_ACTION_TO_CPU,
1915 */
1916rtk_api_ret_t rtk_l2_limitLearningCntAction_get(rtk_port_t port, rtk_l2_limitLearnCntAction_t *pAction)
1917{
1918    rtk_api_ret_t retVal;
1919    rtk_uint32 action;
1920
1921    /* Check initialization state */
1922    RTK_CHK_INIT_STATE();
1923
1924    if (port != RTK_WHOLE_SYSTEM)
1925        return RT_ERR_PORT_ID;
1926
1927    if(NULL == pAction)
1928        return RT_ERR_NULL_POINTER;
1929
1930    if ((retVal = rtl8367c_getAsicLutLearnOverAct(&action)) != RT_ERR_OK)
1931        return retVal;
1932
1933    if ( 1 == action )
1934        *pAction = LIMIT_LEARN_CNT_ACTION_DROP;
1935    else if ( 0 == action )
1936        *pAction = LIMIT_LEARN_CNT_ACTION_FORWARD;
1937    else if ( 2 == action )
1938        *pAction = LIMIT_LEARN_CNT_ACTION_TO_CPU;
1939    else
1940    *pAction = action;
1941
1942    return RT_ERR_OK;
1943}
1944
1945/* Function Name:
1946 *      rtk_l2_limitSystemLearningCntAction_set
1947 * Description:
1948 *      Configure system auto learn over limit number action.
1949 * Input:
1950 *      port - Port id.
1951 *      action - Auto learning entries limit number
1952 * Output:
1953 *      None
1954 * Return:
1955 *      RT_ERR_OK           - OK
1956 *      RT_ERR_FAILED       - Failed
1957 *      RT_ERR_SMI          - SMI access error
1958 *      RT_ERR_PORT_ID      - Invalid port number.
1959 *      RT_ERR_NOT_ALLOWED  - Invalid learn over action
1960 * Note:
1961 *      The API can set SA unknown packet action while auto learn limit number is over
1962 *      The action symbol as following:
1963 *      - LIMIT_LEARN_CNT_ACTION_DROP,
1964 *      - LIMIT_LEARN_CNT_ACTION_FORWARD,
1965 *      - LIMIT_LEARN_CNT_ACTION_TO_CPU,
1966 */
1967rtk_api_ret_t rtk_l2_limitSystemLearningCntAction_set(rtk_l2_limitLearnCntAction_t action)
1968{
1969    rtk_api_ret_t retVal;
1970    rtk_uint32 data;
1971
1972    /* Check initialization state */
1973    RTK_CHK_INIT_STATE();
1974
1975    if ( LIMIT_LEARN_CNT_ACTION_DROP == action )
1976        data = 1;
1977    else if ( LIMIT_LEARN_CNT_ACTION_FORWARD == action )
1978        data = 0;
1979    else if ( LIMIT_LEARN_CNT_ACTION_TO_CPU == action )
1980        data = 2;
1981    else
1982        return RT_ERR_NOT_ALLOWED;
1983
1984    if ((retVal = rtl8367c_setAsicSystemLutLearnOverAct(data)) != RT_ERR_OK)
1985        return retVal;
1986
1987    return RT_ERR_OK;
1988}
1989
1990/* Function Name:
1991 *      rtk_l2_limitSystemLearningCntAction_get
1992 * Description:
1993 *      Get system auto learn over limit number action.
1994 * Input:
1995 *      None.
1996 * Output:
1997 *      pAction - Learn over action
1998 * Return:
1999 *      RT_ERR_OK           - OK
2000 *      RT_ERR_FAILED       - Failed
2001 *      RT_ERR_SMI          - SMI access error
2002 *      RT_ERR_PORT_ID      - Invalid port number.
2003 * Note:
2004 *      The API can get SA unknown packet action while auto learn limit number is over
2005 *      The action symbol as following:
2006 *      - LIMIT_LEARN_CNT_ACTION_DROP,
2007 *      - LIMIT_LEARN_CNT_ACTION_FORWARD,
2008 *      - LIMIT_LEARN_CNT_ACTION_TO_CPU,
2009 */
2010rtk_api_ret_t rtk_l2_limitSystemLearningCntAction_get(rtk_l2_limitLearnCntAction_t *pAction)
2011{
2012    rtk_api_ret_t retVal;
2013    rtk_uint32 action;
2014
2015    /* Check initialization state */
2016    RTK_CHK_INIT_STATE();
2017
2018    if(NULL == pAction)
2019        return RT_ERR_NULL_POINTER;
2020
2021    if ((retVal = rtl8367c_getAsicSystemLutLearnOverAct(&action)) != RT_ERR_OK)
2022        return retVal;
2023
2024    if ( 1 == action )
2025        *pAction = LIMIT_LEARN_CNT_ACTION_DROP;
2026    else if ( 0 == action )
2027        *pAction = LIMIT_LEARN_CNT_ACTION_FORWARD;
2028    else if ( 2 == action )
2029        *pAction = LIMIT_LEARN_CNT_ACTION_TO_CPU;
2030    else
2031    *pAction = action;
2032
2033    return RT_ERR_OK;
2034}
2035
2036/* Function Name:
2037 *      rtk_l2_limitSystemLearningCntPortMask_set
2038 * Description:
2039 *      Configure system auto learn portmask
2040 * Input:
2041 *      pPortmask - Port Mask
2042 * Output:
2043 *      None
2044 * Return:
2045 *      RT_ERR_OK           - OK
2046 *      RT_ERR_FAILED       - Failed
2047 *      RT_ERR_SMI          - SMI access error
2048 *      RT_ERR_PORT_MASK    - Invalid port mask.
2049 * Note:
2050 *
2051 */
2052rtk_api_ret_t rtk_l2_limitSystemLearningCntPortMask_set(rtk_portmask_t *pPortmask)
2053{
2054    rtk_api_ret_t retVal;
2055    rtk_uint32 pmask;
2056
2057    /* Check initialization state */
2058    RTK_CHK_INIT_STATE();
2059
2060    if(NULL == pPortmask)
2061        return RT_ERR_NULL_POINTER;
2062
2063    /* Check port mask */
2064    RTK_CHK_PORTMASK_VALID(pPortmask);
2065
2066    if ((retVal = rtk_switch_portmask_L2P_get(pPortmask, &pmask)) != RT_ERR_OK)
2067        return retVal;
2068
2069    if ((retVal = rtl8367c_setAsicSystemLutLearnPortMask(pmask)) != RT_ERR_OK)
2070        return retVal;
2071
2072    return RT_ERR_OK;
2073}
2074
2075/* Function Name:
2076 *      rtk_l2_limitSystemLearningCntPortMask_get
2077 * Description:
2078 *      get system auto learn portmask
2079 * Input:
2080 *      None
2081 * Output:
2082 *      pPortmask - Port Mask
2083 * Return:
2084 *      RT_ERR_OK           - OK
2085 *      RT_ERR_FAILED       - Failed
2086 *      RT_ERR_SMI          - SMI access error
2087 *      RT_ERR_NULL_POINTER - Null pointer.
2088 * Note:
2089 *
2090 */
2091rtk_api_ret_t rtk_l2_limitSystemLearningCntPortMask_get(rtk_portmask_t *pPortmask)
2092{
2093    rtk_api_ret_t retVal;
2094    rtk_uint32 pmask;
2095
2096    /* Check initialization state */
2097    RTK_CHK_INIT_STATE();
2098
2099    if(NULL == pPortmask)
2100        return RT_ERR_NULL_POINTER;
2101
2102    if ((retVal = rtl8367c_getAsicSystemLutLearnPortMask(&pmask)) != RT_ERR_OK)
2103        return retVal;
2104
2105    if ((retVal = rtk_switch_portmask_P2L_get(pmask, pPortmask)) != RT_ERR_OK)
2106        return retVal;
2107
2108    return RT_ERR_OK;
2109}
2110
2111/* Function Name:
2112 *      rtk_l2_learningCnt_get
2113 * Description:
2114 *      Get per-Port current auto learning number
2115 * Input:
2116 *      port - Port id.
2117 * Output:
2118 *      pMac_cnt - ASIC auto learning entries number
2119 * Return:
2120 *      RT_ERR_OK           - OK
2121 *      RT_ERR_FAILED       - Failed
2122 *      RT_ERR_SMI          - SMI access error
2123 *      RT_ERR_PORT_ID      - Invalid port number.
2124 * Note:
2125 *      The API can get per-port ASIC auto learning number
2126 */
2127rtk_api_ret_t rtk_l2_learningCnt_get(rtk_port_t port, rtk_mac_cnt_t *pMac_cnt)
2128{
2129    rtk_api_ret_t retVal;
2130
2131    /* Check initialization state */
2132    RTK_CHK_INIT_STATE();
2133
2134    /* check port valid */
2135    RTK_CHK_PORT_VALID(port);
2136
2137    if(NULL == pMac_cnt)
2138        return RT_ERR_NULL_POINTER;
2139
2140    if ((retVal = rtl8367c_getAsicLutLearnNo(rtk_switch_port_L2P_get(port), pMac_cnt)) != RT_ERR_OK)
2141        return retVal;
2142
2143    return RT_ERR_OK;
2144}
2145
2146/* Function Name:
2147 *      rtk_l2_floodPortMask_set
2148 * Description:
2149 *      Set flooding portmask
2150 * Input:
2151 *      type - flooding type.
2152 *      pFlood_portmask - flooding porkmask
2153 * Output:
2154 *      None
2155 * Return:
2156 *      RT_ERR_OK           - OK
2157 *      RT_ERR_FAILED       - Failed
2158 *      RT_ERR_SMI          - SMI access error
2159 *      RT_ERR_PORT_MASK    - Invalid portmask.
2160 *      RT_ERR_INPUT        - Invalid input parameters.
2161 * Note:
2162 *      This API can set the flooding mask.
2163 *      The flooding type is as following:
2164 *      - FLOOD_UNKNOWNDA
2165 *      - FLOOD_UNKNOWNMC
2166 *      - FLOOD_BC
2167 */
2168rtk_api_ret_t rtk_l2_floodPortMask_set(rtk_l2_flood_type_t floood_type, rtk_portmask_t *pFlood_portmask)
2169{
2170    rtk_api_ret_t retVal;
2171    rtk_uint32 pmask;
2172
2173    /* Check initialization state */
2174    RTK_CHK_INIT_STATE();
2175
2176    if (floood_type >= FLOOD_END)
2177        return RT_ERR_INPUT;
2178
2179    /* check port valid */
2180    RTK_CHK_PORTMASK_VALID(pFlood_portmask);
2181
2182    /* Get Physical port mask */
2183    if ((retVal = rtk_switch_portmask_L2P_get(pFlood_portmask, &pmask))!=RT_ERR_OK)
2184        return retVal;
2185
2186    switch (floood_type)
2187    {
2188        case FLOOD_UNKNOWNDA:
2189            if ((retVal = rtl8367c_setAsicPortUnknownDaFloodingPortmask(pmask)) != RT_ERR_OK)
2190                return retVal;
2191            break;
2192        case FLOOD_UNKNOWNMC:
2193            if ((retVal = rtl8367c_setAsicPortUnknownMulticastFloodingPortmask(pmask)) != RT_ERR_OK)
2194                return retVal;
2195            break;
2196        case FLOOD_BC:
2197            if ((retVal = rtl8367c_setAsicPortBcastFloodingPortmask(pmask)) != RT_ERR_OK)
2198                return retVal;
2199            break;
2200        default:
2201            break;
2202    }
2203
2204    return RT_ERR_OK;
2205}
2206/* Function Name:
2207 *      rtk_l2_floodPortMask_get
2208 * Description:
2209 *      Get flooding portmask
2210 * Input:
2211 *      type - flooding type.
2212 * Output:
2213 *      pFlood_portmask - flooding porkmask
2214 * Return:
2215 *      RT_ERR_OK           - OK
2216 *      RT_ERR_FAILED       - Failed
2217 *      RT_ERR_SMI          - SMI access error
2218 *      RT_ERR_PORT_ID      - Invalid port number.
2219 * Note:
2220 *      This API can get the flooding mask.
2221 *      The flooding type is as following:
2222 *      - FLOOD_UNKNOWNDA
2223 *      - FLOOD_UNKNOWNMC
2224 *      - FLOOD_BC
2225 */
2226rtk_api_ret_t rtk_l2_floodPortMask_get(rtk_l2_flood_type_t floood_type, rtk_portmask_t *pFlood_portmask)
2227{
2228    rtk_api_ret_t retVal;
2229    rtk_uint32 pmask;
2230
2231    /* Check initialization state */
2232    RTK_CHK_INIT_STATE();
2233
2234    if (floood_type >= FLOOD_END)
2235        return RT_ERR_INPUT;
2236
2237    if(NULL == pFlood_portmask)
2238        return RT_ERR_NULL_POINTER;
2239
2240    switch (floood_type)
2241    {
2242        case FLOOD_UNKNOWNDA:
2243            if ((retVal = rtl8367c_getAsicPortUnknownDaFloodingPortmask(&pmask)) != RT_ERR_OK)
2244                return retVal;
2245            break;
2246        case FLOOD_UNKNOWNMC:
2247            if ((retVal = rtl8367c_getAsicPortUnknownMulticastFloodingPortmask(&pmask)) != RT_ERR_OK)
2248                return retVal;
2249            break;
2250        case FLOOD_BC:
2251            if ((retVal = rtl8367c_getAsicPortBcastFloodingPortmask(&pmask)) != RT_ERR_OK)
2252                return retVal;
2253            break;
2254        default:
2255            break;
2256    }
2257
2258    /* Get Logical port mask */
2259    if ((retVal = rtk_switch_portmask_P2L_get(pmask, pFlood_portmask))!=RT_ERR_OK)
2260        return retVal;
2261
2262    return RT_ERR_OK;
2263}
2264
2265/* Function Name:
2266 *      rtk_l2_localPktPermit_set
2267 * Description:
2268 *      Set permittion of frames if source port and destination port are the same.
2269 * Input:
2270 *      port - Port id.
2271 *      permit - permittion status
2272 * Output:
2273 *      None
2274 * Return:
2275 *      RT_ERR_OK           - OK
2276 *      RT_ERR_FAILED       - Failed
2277 *      RT_ERR_SMI          - SMI access error
2278 *      RT_ERR_PORT_ID      - Invalid port number.
2279 *      RT_ERR_ENABLE       - Invalid permit value.
2280 * Note:
2281 *      This API is setted to permit frame if its source port is equal to destination port.
2282 */
2283rtk_api_ret_t rtk_l2_localPktPermit_set(rtk_port_t port, rtk_enable_t permit)
2284{
2285    rtk_api_ret_t retVal;
2286
2287    /* Check initialization state */
2288    RTK_CHK_INIT_STATE();
2289
2290    /* check port valid */
2291    RTK_CHK_PORT_VALID(port);
2292
2293    if (permit >= RTK_ENABLE_END)
2294        return RT_ERR_ENABLE;
2295
2296    if ((retVal = rtl8367c_setAsicPortBlockSpa(rtk_switch_port_L2P_get(port), permit)) != RT_ERR_OK)
2297        return retVal;
2298
2299    return RT_ERR_OK;
2300}
2301
2302/* Function Name:
2303 *      rtk_l2_localPktPermit_get
2304 * Description:
2305 *      Get permittion of frames if source port and destination port are the same.
2306 * Input:
2307 *      port - Port id.
2308 * Output:
2309 *      pPermit - permittion status
2310 * Return:
2311 *      RT_ERR_OK           - OK
2312 *      RT_ERR_FAILED       - Failed
2313 *      RT_ERR_SMI          - SMI access error
2314 *      RT_ERR_PORT_ID      - Invalid port number.
2315 * Note:
2316 *      This API is to get permittion status for frames if its source port is equal to destination port.
2317 */
2318rtk_api_ret_t rtk_l2_localPktPermit_get(rtk_port_t port, rtk_enable_t *pPermit)
2319{
2320    rtk_api_ret_t retVal;
2321
2322    /* Check initialization state */
2323    RTK_CHK_INIT_STATE();
2324
2325    /* check port valid */
2326    RTK_CHK_PORT_VALID(port);
2327
2328    if(NULL == pPermit)
2329        return RT_ERR_NULL_POINTER;
2330
2331    if ((retVal = rtl8367c_getAsicPortBlockSpa(rtk_switch_port_L2P_get(port), pPermit)) != RT_ERR_OK)
2332        return retVal;
2333
2334    return RT_ERR_OK;
2335}
2336
2337/* Function Name:
2338 *      rtk_l2_aging_set
2339 * Description:
2340 *      Set LUT agging out speed
2341 * Input:
2342 *      aging_time - Agging out time.
2343 * Output:
2344 *      None
2345 * Return:
2346 *      RT_ERR_OK               - OK
2347 *      RT_ERR_FAILED           - Failed
2348 *      RT_ERR_SMI              - SMI access error
2349 *      RT_ERR_OUT_OF_RANGE     - input out of range.
2350 * Note:
2351 *      The API can set LUT agging out period for each entry and the range is from 45s to 458s.
2352 */
2353rtk_api_ret_t rtk_l2_aging_set(rtk_l2_age_time_t aging_time)
2354{
2355    rtk_uint32 i;
2356    CONST_T rtk_uint32 agePara[10][3] = {
2357        {45, 0, 1}, {88, 0, 2}, {133, 0, 3}, {177, 0, 4}, {221, 0, 5}, {266, 0, 6}, {310, 0, 7},
2358        {354, 2, 6}, {413, 2, 7}, {458, 3, 7}};
2359
2360    /* Check initialization state */
2361    RTK_CHK_INIT_STATE();
2362
2363    if (aging_time>agePara[9][0])
2364        return RT_ERR_OUT_OF_RANGE;
2365
2366    for (i = 0; i<10; i++)
2367    {
2368        if (aging_time<=agePara[i][0])
2369        {
2370            return rtl8367c_setAsicLutAgeTimerSpeed(agePara[i][2], agePara[i][1]);
2371        }
2372    }
2373
2374    return RT_ERR_FAILED;
2375}
2376
2377/* Function Name:
2378 *      rtk_l2_aging_get
2379 * Description:
2380 *      Get LUT agging out time
2381 * Input:
2382 *      None
2383 * Output:
2384 *      pEnable - Aging status
2385 * Return:
2386 *      RT_ERR_OK           - OK
2387 *      RT_ERR_FAILED       - Failed
2388 *      RT_ERR_SMI          - SMI access error
2389 *      RT_ERR_PORT_ID      - Invalid port number.
2390 * Note:
2391 *      The API can get LUT agging out period for each entry.
2392 */
2393rtk_api_ret_t rtk_l2_aging_get(rtk_l2_age_time_t *pAging_time)
2394{
2395    rtk_api_ret_t retVal;
2396    rtk_uint32 i,time, speed;
2397    CONST_T rtk_uint32 agePara[10][3] = {
2398        {45, 0, 1}, {88, 0, 2}, {133, 0, 3}, {177, 0, 4}, {221, 0, 5}, {266, 0, 6}, {310, 0, 7},
2399        {354, 2, 6}, {413, 2, 7}, {458, 3, 7}};
2400
2401    /* Check initialization state */
2402    RTK_CHK_INIT_STATE();
2403
2404    if(NULL == pAging_time)
2405        return RT_ERR_NULL_POINTER;
2406
2407    if ((retVal = rtl8367c_getAsicLutAgeTimerSpeed(&time, &speed)) != RT_ERR_OK)
2408        return retVal;
2409
2410    for (i = 0; i<10; i++)
2411    {
2412        if (time==agePara[i][2]&&speed==agePara[i][1])
2413        {
2414            *pAging_time = agePara[i][0];
2415            return RT_ERR_OK;
2416        }
2417    }
2418
2419    return RT_ERR_FAILED;
2420}
2421
2422/* Function Name:
2423 *      rtk_l2_ipMcastAddrLookup_set
2424 * Description:
2425 *      Set Lut IP multicast lookup function
2426 * Input:
2427 *      type - Lookup type for IPMC packet.
2428 * Output:
2429 *      None.
2430 * Return:
2431 *      RT_ERR_OK          - OK
2432 *      RT_ERR_FAILED      - Failed
2433 *      RT_ERR_SMI         - SMI access error
2434 * Note:
2435 *      LOOKUP_MAC      - Lookup by MAC address
2436 *      LOOKUP_IP       - Lookup by IP address
2437 *      LOOKUP_IP_VID   - Lookup by IP address & VLAN ID
2438 */
2439rtk_api_ret_t rtk_l2_ipMcastAddrLookup_set(rtk_l2_ipmc_lookup_type_t type)
2440{
2441    rtk_api_ret_t retVal;
2442
2443    /* Check initialization state */
2444    RTK_CHK_INIT_STATE();
2445
2446    if(type == LOOKUP_MAC)
2447    {
2448        if((retVal = rtl8367c_setAsicLutIpMulticastLookup(DISABLED)) != RT_ERR_OK)
2449            return retVal;
2450    }
2451    else if(type == LOOKUP_IP)
2452    {
2453        if((retVal = rtl8367c_setAsicLutIpMulticastLookup(ENABLED)) != RT_ERR_OK)
2454            return retVal;
2455
2456        if ((retVal = rtl8367c_setAsicLutIpMulticastVidLookup(DISABLED))!=RT_ERR_OK)
2457            return retVal;
2458
2459        if ((retVal = rtl8367c_setAsicLutIpLookupMethod(1))!=RT_ERR_OK)
2460            return retVal;
2461    }
2462    else if(type == LOOKUP_IP_VID)
2463    {
2464        if((retVal = rtl8367c_setAsicLutIpMulticastLookup(ENABLED)) != RT_ERR_OK)
2465            return retVal;
2466
2467        if ((retVal = rtl8367c_setAsicLutIpMulticastVidLookup(ENABLED))!=RT_ERR_OK)
2468            return retVal;
2469
2470        if ((retVal = rtl8367c_setAsicLutIpLookupMethod(1))!=RT_ERR_OK)
2471            return retVal;
2472    }
2473    else
2474        return RT_ERR_INPUT;
2475
2476    return RT_ERR_OK;
2477}
2478
2479/* Function Name:
2480 *      rtk_l2_ipMcastAddrLookup_get
2481 * Description:
2482 *      Get Lut IP multicast lookup function
2483 * Input:
2484 *      None.
2485 * Output:
2486 *      pType - Lookup type for IPMC packet.
2487 * Return:
2488 *      RT_ERR_OK          - OK
2489 *      RT_ERR_FAILED      - Failed
2490 *      RT_ERR_SMI         - SMI access error
2491 * Note:
2492 *      None.
2493 */
2494rtk_api_ret_t rtk_l2_ipMcastAddrLookup_get(rtk_l2_ipmc_lookup_type_t *pType)
2495{
2496    rtk_api_ret_t       retVal;
2497    rtk_uint32          enabled, vid_lookup;
2498
2499    /* Check initialization state */
2500    RTK_CHK_INIT_STATE();
2501
2502    if(NULL == pType)
2503        return RT_ERR_NULL_POINTER;
2504
2505    if((retVal = rtl8367c_getAsicLutIpMulticastLookup(&enabled)) != RT_ERR_OK)
2506        return retVal;
2507
2508    if ((retVal = rtl8367c_getAsicLutIpMulticastVidLookup(&vid_lookup))!=RT_ERR_OK)
2509        return retVal;
2510
2511    if(enabled == ENABLED)
2512    {
2513        if(vid_lookup == ENABLED)
2514            *pType = LOOKUP_IP_VID;
2515        else
2516            *pType = LOOKUP_IP;
2517    }
2518    else
2519        *pType = LOOKUP_MAC;
2520
2521    return RT_ERR_OK;
2522}
2523
2524/* Function Name:
2525 *      rtk_l2_ipMcastForwardRouterPort_set
2526 * Description:
2527 *      Set IPMC packet forward to rounter port also or not
2528 * Input:
2529 *      enabled - 1: Inlcude router port, 0, exclude router port
2530 * Output:
2531 *      None.
2532 * Return:
2533 *      RT_ERR_OK          - OK
2534 *      RT_ERR_FAILED      - Failed
2535 *      RT_ERR_SMI         - SMI access error
2536 * Note:
2537 *
2538 */
2539rtk_api_ret_t rtk_l2_ipMcastForwardRouterPort_set(rtk_enable_t enabled)
2540{
2541    rtk_api_ret_t       retVal;
2542
2543    /* Check initialization state */
2544    RTK_CHK_INIT_STATE();
2545
2546    if (enabled >= RTK_ENABLE_END)
2547        return RT_ERR_ENABLE;
2548
2549    if((retVal = rtl8367c_setAsicLutIpmcFwdRouterPort(enabled)) != RT_ERR_OK)
2550        return retVal;
2551
2552    return RT_ERR_OK;
2553}
2554
2555/* Function Name:
2556 *      rtk_l2_ipMcastForwardRouterPort_get
2557 * Description:
2558 *      Get IPMC packet forward to rounter port also or not
2559 * Input:
2560 *      None.
2561 * Output:
2562 *      pEnabled    - 1: Inlcude router port, 0, exclude router port
2563 * Return:
2564 *      RT_ERR_OK           - OK
2565 *      RT_ERR_FAILED       - Failed
2566 *      RT_ERR_NULL_POINTER - Null pointer
2567 * Note:
2568 *
2569 */
2570rtk_api_ret_t rtk_l2_ipMcastForwardRouterPort_get(rtk_enable_t *pEnabled)
2571{
2572    rtk_api_ret_t       retVal;
2573
2574    /* Check initialization state */
2575    RTK_CHK_INIT_STATE();
2576
2577    if (NULL == pEnabled)
2578        return RT_ERR_NULL_POINTER;
2579
2580    if((retVal = rtl8367c_getAsicLutIpmcFwdRouterPort(pEnabled)) != RT_ERR_OK)
2581        return retVal;
2582
2583    return RT_ERR_OK;
2584}
2585
2586/* Function Name:
2587 *      rtk_l2_ipMcastGroupEntry_add
2588 * Description:
2589 *      Add an IP Multicast entry to group table
2590 * Input:
2591 *      ip_addr     - IP address
2592 *      vid         - VLAN ID
2593 *      pPortmask   - portmask
2594 * Output:
2595 *      None.
2596 * Return:
2597 *      RT_ERR_OK          - OK
2598 *      RT_ERR_FAILED      - Failed
2599 *      RT_ERR_SMI         - SMI access error
2600 *      RT_ERR_TBL_FULL    - Table Full
2601 * Note:
2602 *      Add an entry to IP Multicast Group table.
2603 */
2604rtk_api_ret_t rtk_l2_ipMcastGroupEntry_add(ipaddr_t ip_addr, rtk_uint32 vid, rtk_portmask_t *pPortmask)
2605{
2606    rtk_uint32      empty_idx = 0xFFFF;
2607    rtk_int32       index;
2608    ipaddr_t        group_addr;
2609    rtk_uint32      group_vid;
2610    rtk_uint32      pmask;
2611    rtk_uint32      valid;
2612    rtk_uint32      physicalPortmask;
2613    rtk_api_ret_t   retVal;
2614
2615    /* Check initialization state */
2616    RTK_CHK_INIT_STATE();
2617
2618    if (vid > RTL8367C_VIDMAX)
2619        return RT_ERR_L2_VID;
2620
2621    if(NULL == pPortmask)
2622        return RT_ERR_NULL_POINTER;
2623
2624    if((ip_addr & 0xF0000000) != 0xE0000000)
2625        return RT_ERR_INPUT;
2626
2627    /* Get Physical port mask */
2628    if ((retVal = rtk_switch_portmask_L2P_get(pPortmask, &physicalPortmask))!=RT_ERR_OK)
2629        return retVal;
2630
2631    for(index = 0; index <= RTL8367C_LUT_IPMCGRP_TABLE_MAX; index++)
2632    {
2633        if ((retVal = rtl8367c_getAsicLutIPMCGroup((rtk_uint32)index, &group_addr, &group_vid, &pmask, &valid))!=RT_ERR_OK)
2634            return retVal;
2635
2636        if( (valid == ENABLED) && (group_addr == ip_addr) && (group_vid == vid) )
2637        {
2638            if(pmask != physicalPortmask)
2639            {
2640                pmask = physicalPortmask;
2641                if ((retVal = rtl8367c_setAsicLutIPMCGroup(index, ip_addr, vid, pmask, valid))!=RT_ERR_OK)
2642                    return retVal;
2643            }
2644
2645            return RT_ERR_OK;
2646        }
2647
2648        if( (valid == DISABLED) && (empty_idx == 0xFFFF) ) /* Unused */
2649            empty_idx = (rtk_uint32)index;
2650    }
2651
2652    if(empty_idx == 0xFFFF)
2653        return RT_ERR_TBL_FULL;
2654
2655    pmask = physicalPortmask;
2656    if ((retVal = rtl8367c_setAsicLutIPMCGroup(empty_idx, ip_addr, vid, pmask, ENABLED))!=RT_ERR_OK)
2657        return retVal;
2658
2659    return RT_ERR_OK;
2660}
2661
2662/* Function Name:
2663 *      rtk_l2_ipMcastGroupEntry_del
2664 * Description:
2665 *      Delete an entry from IP Multicast group table
2666 * Input:
2667 *      ip_addr     - IP address
2668 *      vid         - VLAN ID
2669 * Output:
2670 *      None.
2671 * Return:
2672 *      RT_ERR_OK          - OK
2673 *      RT_ERR_FAILED      - Failed
2674 *      RT_ERR_SMI         - SMI access error
2675 *      RT_ERR_TBL_FULL    - Table Full
2676 * Note:
2677 *      Delete an entry from IP Multicast group table.
2678 */
2679rtk_api_ret_t rtk_l2_ipMcastGroupEntry_del(ipaddr_t ip_addr, rtk_uint32 vid)
2680{
2681    rtk_int32       index;
2682    ipaddr_t        group_addr;
2683    rtk_uint32      group_vid;
2684    rtk_uint32      pmask;
2685    rtk_uint32      valid;
2686    rtk_api_ret_t   retVal;
2687
2688    /* Check initialization state */
2689    RTK_CHK_INIT_STATE();
2690
2691    if (vid > RTL8367C_VIDMAX)
2692        return RT_ERR_L2_VID;
2693
2694    if((ip_addr & 0xF0000000) != 0xE0000000)
2695        return RT_ERR_INPUT;
2696
2697    for(index = 0; index <= RTL8367C_LUT_IPMCGRP_TABLE_MAX; index++)
2698    {
2699        if ((retVal = rtl8367c_getAsicLutIPMCGroup((rtk_uint32)index, &group_addr, &group_vid, &pmask, &valid))!=RT_ERR_OK)
2700            return retVal;
2701
2702        if( (valid == ENABLED) && (group_addr == ip_addr) && (group_vid == vid) )
2703        {
2704            group_addr = 0xE0000000;
2705            group_vid = 0;
2706            pmask = 0;
2707            if ((retVal = rtl8367c_setAsicLutIPMCGroup(index, group_addr, group_vid, pmask, DISABLED))!=RT_ERR_OK)
2708                return retVal;
2709
2710            return RT_ERR_OK;
2711        }
2712    }
2713
2714    return RT_ERR_FAILED;
2715}
2716
2717/* Function Name:
2718 *      rtk_l2_ipMcastGroupEntry_get
2719 * Description:
2720 *      get an entry from IP Multicast group table
2721 * Input:
2722 *      ip_addr     - IP address
2723 *      vid         - VLAN ID
2724 * Output:
2725 *      pPortmask   - member port mask
2726 * Return:
2727 *      RT_ERR_OK          - OK
2728 *      RT_ERR_FAILED      - Failed
2729 *      RT_ERR_SMI         - SMI access error
2730 *      RT_ERR_TBL_FULL    - Table Full
2731 * Note:
2732 *      Delete an entry from IP Multicast group table.
2733 */
2734rtk_api_ret_t rtk_l2_ipMcastGroupEntry_get(ipaddr_t ip_addr, rtk_uint32 vid, rtk_portmask_t *pPortmask)
2735{
2736    rtk_int32       index;
2737    ipaddr_t        group_addr;
2738    rtk_uint32      group_vid;
2739    rtk_uint32      valid;
2740    rtk_uint32      pmask;
2741    rtk_api_ret_t   retVal;
2742
2743    /* Check initialization state */
2744    RTK_CHK_INIT_STATE();
2745
2746    if((ip_addr & 0xF0000000) != 0xE0000000)
2747        return RT_ERR_INPUT;
2748
2749    if (vid > RTL8367C_VIDMAX)
2750        return RT_ERR_L2_VID;
2751
2752    if(NULL == pPortmask)
2753        return RT_ERR_NULL_POINTER;
2754
2755    for(index = 0; index <= RTL8367C_LUT_IPMCGRP_TABLE_MAX; index++)
2756    {
2757        if ((retVal = rtl8367c_getAsicLutIPMCGroup((rtk_uint32)index, &group_addr, &group_vid, &pmask, &valid))!=RT_ERR_OK)
2758            return retVal;
2759
2760        if( (valid == ENABLED) && (group_addr == ip_addr) && (group_vid == vid) )
2761        {
2762            if ((retVal = rtk_switch_portmask_P2L_get(pmask, pPortmask))!=RT_ERR_OK)
2763                return retVal;
2764
2765            return RT_ERR_OK;
2766        }
2767    }
2768
2769    return RT_ERR_FAILED;
2770}
2771
2772/* Function Name:
2773 *      rtk_l2_entry_get
2774 * Description:
2775 *      Get LUT unicast entry.
2776 * Input:
2777 *      pL2_entry - Index field in the structure.
2778 * Output:
2779 *      pL2_entry - other fields such as MAC, port, age...
2780 * Return:
2781 *      RT_ERR_OK               - OK
2782 *      RT_ERR_FAILED           - Failed
2783 *      RT_ERR_SMI              - SMI access error
2784 *      RT_ERR_L2_EMPTY_ENTRY   - Empty LUT entry.
2785 *      RT_ERR_INPUT            - Invalid input parameters.
2786 * Note:
2787 *      This API is used to get address by index from 0~2111.
2788 */
2789rtk_api_ret_t rtk_l2_entry_get(rtk_l2_addr_table_t *pL2_entry)
2790{
2791    rtk_api_ret_t retVal;
2792    rtk_uint32 method;
2793    rtl8367c_luttb l2Table;
2794
2795    /* Check initialization state */
2796    RTK_CHK_INIT_STATE();
2797
2798    if (pL2_entry->index >= rtk_switch_maxLutAddrNumber_get())
2799        return RT_ERR_INPUT;
2800
2801    l2Table.address= pL2_entry->index;
2802    method = LUTREADMETHOD_ADDRESS;
2803    if ((retVal = rtl8367c_getAsicL2LookupTb(method, &l2Table)) != RT_ERR_OK)
2804        return retVal;
2805
2806    if ((pL2_entry->index>0x800)&&(l2Table.lookup_hit==0))
2807         return RT_ERR_L2_EMPTY_ENTRY;
2808
2809    if(l2Table.l3lookup)
2810    {
2811        if(l2Table.l3vidlookup)
2812        {
2813            memset(&pL2_entry->mac, 0, sizeof(rtk_mac_t));
2814            pL2_entry->is_ipmul  = l2Table.l3lookup;
2815            pL2_entry->sip       = l2Table.sip;
2816            pL2_entry->dip       = l2Table.dip;
2817            pL2_entry->is_static = l2Table.nosalearn;
2818
2819            /* Get Logical port mask */
2820            if ((retVal = rtk_switch_portmask_P2L_get(l2Table.mbr, &(pL2_entry->portmask)))!=RT_ERR_OK)
2821                return retVal;
2822
2823            pL2_entry->fid       = 0;
2824            pL2_entry->age       = 0;
2825            pL2_entry->auth      = 0;
2826            pL2_entry->sa_block  = 0;
2827            pL2_entry->is_ipvidmul = 1;
2828            pL2_entry->l3_vid      = l2Table.l3_vid;
2829        }
2830        else
2831        {
2832            memset(&pL2_entry->mac, 0, sizeof(rtk_mac_t));
2833            pL2_entry->is_ipmul  = l2Table.l3lookup;
2834            pL2_entry->sip       = l2Table.sip;
2835            pL2_entry->dip       = l2Table.dip;
2836            pL2_entry->is_static = l2Table.nosalearn;
2837
2838            /* Get Logical port mask */
2839            if ((retVal = rtk_switch_portmask_P2L_get(l2Table.mbr, &(pL2_entry->portmask)))!=RT_ERR_OK)
2840                return retVal;
2841
2842            pL2_entry->fid       = 0;
2843            pL2_entry->age       = 0;
2844            pL2_entry->auth      = 0;
2845            pL2_entry->sa_block  = 0;
2846            pL2_entry->is_ipvidmul = 0;
2847            pL2_entry->l3_vid      = 0;
2848        }
2849    }
2850    else if(l2Table.mac.octet[0]&0x01)
2851    {
2852        memset(&pL2_entry->sip, 0, sizeof(ipaddr_t));
2853        memset(&pL2_entry->dip, 0, sizeof(ipaddr_t));
2854        pL2_entry->mac.octet[0] = l2Table.mac.octet[0];
2855        pL2_entry->mac.octet[1] = l2Table.mac.octet[1];
2856        pL2_entry->mac.octet[2] = l2Table.mac.octet[2];
2857        pL2_entry->mac.octet[3] = l2Table.mac.octet[3];
2858        pL2_entry->mac.octet[4] = l2Table.mac.octet[4];
2859        pL2_entry->mac.octet[5] = l2Table.mac.octet[5];
2860        pL2_entry->is_ipmul  = l2Table.l3lookup;
2861        pL2_entry->is_static = l2Table.nosalearn;
2862
2863        /* Get Logical port mask */
2864        if ((retVal = rtk_switch_portmask_P2L_get(l2Table.mbr, &(pL2_entry->portmask)))!=RT_ERR_OK)
2865            return retVal;
2866
2867        pL2_entry->ivl       = l2Table.ivl_svl;
2868        if(l2Table.ivl_svl == 1) /* IVL */
2869        {
2870            pL2_entry->cvid      = l2Table.cvid_fid;
2871            pL2_entry->fid       = 0;
2872        }
2873        else /* SVL*/
2874        {
2875            pL2_entry->cvid      = 0;
2876            pL2_entry->fid       = l2Table.cvid_fid;
2877        }
2878        pL2_entry->auth      = l2Table.auth;
2879        pL2_entry->sa_block  = l2Table.sa_block;
2880        pL2_entry->age       = 0;
2881        pL2_entry->is_ipvidmul = 0;
2882        pL2_entry->l3_vid      = 0;
2883    }
2884    else if((l2Table.age != 0)||(l2Table.nosalearn == 1))
2885    {
2886        memset(&pL2_entry->sip, 0, sizeof(ipaddr_t));
2887        memset(&pL2_entry->dip, 0, sizeof(ipaddr_t));
2888        pL2_entry->mac.octet[0] = l2Table.mac.octet[0];
2889        pL2_entry->mac.octet[1] = l2Table.mac.octet[1];
2890        pL2_entry->mac.octet[2] = l2Table.mac.octet[2];
2891        pL2_entry->mac.octet[3] = l2Table.mac.octet[3];
2892        pL2_entry->mac.octet[4] = l2Table.mac.octet[4];
2893        pL2_entry->mac.octet[5] = l2Table.mac.octet[5];
2894        pL2_entry->is_ipmul  = l2Table.l3lookup;
2895        pL2_entry->is_static = l2Table.nosalearn;
2896
2897        /* Get Logical port mask */
2898        if ((retVal = rtk_switch_portmask_P2L_get(1<<(l2Table.spa), &(pL2_entry->portmask)))!=RT_ERR_OK)
2899            return retVal;
2900
2901        pL2_entry->ivl       = l2Table.ivl_svl;
2902        pL2_entry->cvid      = l2Table.cvid_fid;
2903        pL2_entry->fid       = l2Table.fid;
2904        pL2_entry->auth      = l2Table.auth;
2905        pL2_entry->sa_block  = l2Table.sa_block;
2906        pL2_entry->age       = l2Table.age;
2907        pL2_entry->is_ipvidmul = 0;
2908        pL2_entry->l3_vid      = 0;
2909    }
2910    else
2911       return RT_ERR_L2_EMPTY_ENTRY;
2912
2913    return RT_ERR_OK;
2914}
2915
2916
2917