4 * @brief Implementation of the public API
7 * IXP400 SW Release version 2.0
9 * -- Copyright Notice --
12 * Copyright 2001-2005, Intel Corporation.
13 * All rights reserved.
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
24 * 3. Neither the name of the Intel Corporation nor the names of its contributors
25 * may be used to endorse or promote products derived from this software
26 * without specific prior written permission.
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
30 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
42 * -- End of Copyright Notice --
45 #include "IxEthDB_p.h"
47 extern HashTable dbHashtable
;
48 IX_ETH_DB_PRIVATE
void ixEthDBPortInfoShow(IxEthDBPortId portID
, IxEthDBRecordType recordFilter
);
49 IX_ETH_DB_PRIVATE IxEthDBStatus
ixEthDBHeaderShow(IxEthDBRecordType recordFilter
);
50 IX_ETH_DB_PUBLIC IxEthDBStatus
ixEthDBDependencyPortMapShow(IxEthDBPortId portID
, IxEthDBPortMap map
);
53 * @brief displays a port dependency map
55 * @param portID ID of the port
56 * @param map port map to display
58 * @return IX_ETH_DB_SUCCESS if the operation completed
62 IxEthDBStatus
ixEthDBDependencyPortMapShow(IxEthDBPortId portID
, IxEthDBPortMap map
)
65 BOOL mapSelf
= TRUE
, mapNone
= TRUE
, firstPort
= TRUE
;
67 /* dependency port maps */
68 printf("Dependency port map: ");
70 /* browse the port map */
71 for (portIndex
= 0 ; portIndex
< IX_ETH_DB_NUMBER_OF_PORTS
; portIndex
++)
73 if (IS_PORT_INCLUDED(portIndex
, map
))
77 if (portIndex
!= portID
)
82 printf("%s%d", firstPort
? "{" : ", ", portIndex
);
93 printf("%s (%s)\n", firstPort
? "" : "}", mapSelf
? "self" : mapNone
? "none" : "group");
95 return IX_ETH_DB_SUCCESS
;
99 * @brief displays all the filtering records belonging to a port
101 * @param portID ID of the port to display
103 * Note that this function is documented in the main component
104 * header file, IxEthDB.h.
106 * @warning deprecated, use @ref ixEthDBFilteringDatabaseShowRecords()
107 * instead. Calling this function is equivalent to calling
108 * ixEthDBFilteringDatabaseShowRecords(portID, IX_ETH_DB_FILTERING_RECORD)
111 IxEthDBStatus
ixEthDBFilteringDatabaseShow(IxEthDBPortId portID
)
113 IxEthDBStatus local_result
;
114 HashIterator iterator
;
116 UINT32 recordCount
= 0;
118 IX_ETH_DB_CHECK_PORT(portID
);
120 IX_ETH_DB_CHECK_SINGLE_NPE(portID
);
122 portInfo
= &ixEthDBPortInfo
[portID
];
124 /* display table header */
125 printf("Ethernet database records for port ID [%d]\n", portID
);
127 ixEthDBDependencyPortMapShow(portID
, portInfo
->dependencyPortMap
);
129 if (ixEthDBPortDefinitions
[portID
].type
== IX_ETH_NPE
)
131 printf("NPE updates are %s\n\n", portInfo
->updateMethod
.updateEnabled
? "enabled" : "disabled");
135 printf("updates disabled (not an NPE)\n\n");
138 printf(" MAC address | Age | Type \n");
139 printf("___________________________________\n");
141 /* browse database */
142 BUSY_RETRY(ixEthDBInitHashIterator(&dbHashtable
, &iterator
));
144 while (IS_ITERATOR_VALID(&iterator
))
146 MacDescriptor
*descriptor
= (MacDescriptor
*) iterator
.node
->data
;
148 if (descriptor
->portID
== portID
&& descriptor
->type
== IX_ETH_DB_FILTERING_RECORD
)
153 printf(" %02X:%02X:%02X:%02X:%02X:%02X | %5d | %s\n",
154 descriptor
->macAddress
[0],
155 descriptor
->macAddress
[1],
156 descriptor
->macAddress
[2],
157 descriptor
->macAddress
[3],
158 descriptor
->macAddress
[4],
159 descriptor
->macAddress
[5],
160 descriptor
->recordData
.filteringData
.age
,
161 descriptor
->recordData
.filteringData
.staticEntry
? "static" : "dynamic");
164 /* move to the next record */
165 BUSY_RETRY_WITH_RESULT(ixEthDBIncrementHashIterator(&dbHashtable
, &iterator
), local_result
);
168 if (local_result
== IX_ETH_DB_BUSY
)
170 return IX_ETH_DB_FAIL
;
174 /* display number of records */
175 printf("\nFound %d records\n", recordCount
);
177 return IX_ETH_DB_SUCCESS
;
181 * @brief displays all the filtering records belonging to all the ports
183 * Note that this function is documented in the main component
184 * header file, IxEthDB.h.
186 * @warning deprecated, use @ref ixEthDBFilteringDatabaseShowRecords()
187 * instead. Calling this function is equivalent to calling
188 * ixEthDBFilteringDatabaseShowRecords(IX_ETH_DB_ALL_PORTS, IX_ETH_DB_FILTERING_RECORD)
191 void ixEthDBFilteringDatabaseShowAll()
193 IxEthDBPortId portIndex
;
195 printf("\nEthernet learning/filtering database: listing %d ports\n\n", (UINT32
) IX_ETH_DB_NUMBER_OF_PORTS
);
197 for (portIndex
= 0 ; portIndex
< IX_ETH_DB_NUMBER_OF_PORTS
; portIndex
++)
199 ixEthDBFilteringDatabaseShow(portIndex
);
201 if (portIndex
< IX_ETH_DB_NUMBER_OF_PORTS
- 1)
209 * @brief displays one record in a format depending on the record filter
211 * @param descriptor pointer to the record
212 * @param recordFilter format filter
214 * This function will display the fields in a record depending on the
215 * selected record filter.
220 void ixEthDBRecordShow(MacDescriptor
*descriptor
, IxEthDBRecordType recordFilter
)
222 if (recordFilter
== IX_ETH_DB_FILTERING_VLAN_RECORD
223 || recordFilter
== (IX_ETH_DB_FILTERING_RECORD
| IX_ETH_DB_FILTERING_VLAN_RECORD
))
225 /* display VLAN record header - leave this commented code in place, its purpose is to align the print format with the header
226 printf(" MAC address | Age | Type | VLAN ID | CFI | QoS class \n");
227 printf("___________________________________________________________________\n"); */
229 if (descriptor
->type
== IX_ETH_DB_FILTERING_VLAN_RECORD
)
231 printf("%02X:%02X:%02X:%02X:%02X:%02X | %3d | %s | %d | %d | %d\n",
232 descriptor
->macAddress
[0],
233 descriptor
->macAddress
[1],
234 descriptor
->macAddress
[2],
235 descriptor
->macAddress
[3],
236 descriptor
->macAddress
[4],
237 descriptor
->macAddress
[5],
238 descriptor
->recordData
.filteringVlanData
.age
,
239 descriptor
->recordData
.filteringVlanData
.staticEntry
? "static" : "dynamic",
240 IX_ETH_DB_GET_VLAN_ID(descriptor
->recordData
.filteringVlanData
.ieee802_1qTag
),
241 (descriptor
->recordData
.filteringVlanData
.ieee802_1qTag
& 0x1000) >> 12,
242 IX_ETH_DB_GET_QOS_PRIORITY(descriptor
->recordData
.filteringVlanData
.ieee802_1qTag
));
244 else if (descriptor
->type
== IX_ETH_DB_FILTERING_RECORD
)
246 printf("%02X:%02X:%02X:%02X:%02X:%02X | %3d | %s | - | - | -\n",
247 descriptor
->macAddress
[0],
248 descriptor
->macAddress
[1],
249 descriptor
->macAddress
[2],
250 descriptor
->macAddress
[3],
251 descriptor
->macAddress
[4],
252 descriptor
->macAddress
[5],
253 descriptor
->recordData
.filteringData
.age
,
254 descriptor
->recordData
.filteringData
.staticEntry
? "static" : "dynamic");
257 else if (recordFilter
== IX_ETH_DB_FILTERING_RECORD
)
259 /* display filtering record header - leave this commented code in place, its purpose is to align the print format with the header
260 printf(" MAC address | Age | Type \n");
261 printf("_______________________________________\n"); */
263 if (descriptor
->type
== IX_ETH_DB_FILTERING_RECORD
)
265 printf("%02X:%02X:%02X:%02X:%02X:%02X | %3d | %s \n",
266 descriptor
->macAddress
[0],
267 descriptor
->macAddress
[1],
268 descriptor
->macAddress
[2],
269 descriptor
->macAddress
[3],
270 descriptor
->macAddress
[4],
271 descriptor
->macAddress
[5],
272 descriptor
->recordData
.filteringData
.age
,
273 descriptor
->recordData
.filteringData
.staticEntry
? "static" : "dynamic");
276 else if (recordFilter
== IX_ETH_DB_WIFI_RECORD
)
278 /* display WiFi record header - leave this commented code in place, its purpose is to align the print format with the header
279 printf(" MAC address | GW MAC address \n");
280 printf("_______________________________________\n"); */
282 if (descriptor
->type
== IX_ETH_DB_WIFI_RECORD
)
284 if (descriptor
->recordData
.wifiData
.type
== IX_ETH_DB_WIFI_AP_TO_AP
)
286 /* gateway address present */
287 printf("%02X:%02X:%02X:%02X:%02X:%02X | %02X:%02X:%02X:%02X:%02X:%02X \n",
288 descriptor
->macAddress
[0],
289 descriptor
->macAddress
[1],
290 descriptor
->macAddress
[2],
291 descriptor
->macAddress
[3],
292 descriptor
->macAddress
[4],
293 descriptor
->macAddress
[5],
294 descriptor
->recordData
.wifiData
.gwMacAddress
[0],
295 descriptor
->recordData
.wifiData
.gwMacAddress
[1],
296 descriptor
->recordData
.wifiData
.gwMacAddress
[2],
297 descriptor
->recordData
.wifiData
.gwMacAddress
[3],
298 descriptor
->recordData
.wifiData
.gwMacAddress
[4],
299 descriptor
->recordData
.wifiData
.gwMacAddress
[5]);
304 printf("%02X:%02X:%02X:%02X:%02X:%02X | ----no gateway----- \n",
305 descriptor
->macAddress
[0],
306 descriptor
->macAddress
[1],
307 descriptor
->macAddress
[2],
308 descriptor
->macAddress
[3],
309 descriptor
->macAddress
[4],
310 descriptor
->macAddress
[5]);
314 else if (recordFilter
== IX_ETH_DB_FIREWALL_RECORD
)
316 /* display Firewall record header - leave this commented code in place, its purpose is to align the print format with the header
317 printf(" MAC address \n");
318 printf("__________________\n"); */
320 if (descriptor
->type
== IX_ETH_DB_FIREWALL_RECORD
)
322 printf("%02X:%02X:%02X:%02X:%02X:%02X \n",
323 descriptor
->macAddress
[0],
324 descriptor
->macAddress
[1],
325 descriptor
->macAddress
[2],
326 descriptor
->macAddress
[3],
327 descriptor
->macAddress
[4],
328 descriptor
->macAddress
[5]);
331 else if (recordFilter
== IX_ETH_DB_ALL_RECORD_TYPES
)
333 /* display composite record header - leave this commented code in place, its purpose is to align the print format with the header
334 printf(" MAC address | Record | Age| Type | VLAN |CFI| QoS | GW MAC address \n");
335 printf("_______________________________________________________________________________\n"); */
337 if (descriptor
->type
== IX_ETH_DB_FILTERING_VLAN_RECORD
)
339 printf("%02X:%02X:%02X:%02X:%02X:%02X | VLAN | %2d | %s | %4d | %1d | %1d | -----------------\n",
340 descriptor
->macAddress
[0],
341 descriptor
->macAddress
[1],
342 descriptor
->macAddress
[2],
343 descriptor
->macAddress
[3],
344 descriptor
->macAddress
[4],
345 descriptor
->macAddress
[5],
346 descriptor
->recordData
.filteringVlanData
.age
,
347 descriptor
->recordData
.filteringVlanData
.staticEntry
? "static " : "dynamic",
348 IX_ETH_DB_GET_VLAN_ID(descriptor
->recordData
.filteringVlanData
.ieee802_1qTag
),
349 (descriptor
->recordData
.filteringVlanData
.ieee802_1qTag
& 0x1000) >> 12,
350 IX_ETH_DB_GET_QOS_PRIORITY(descriptor
->recordData
.filteringVlanData
.ieee802_1qTag
));
352 else if (descriptor
->type
== IX_ETH_DB_FILTERING_RECORD
)
354 printf("%02X:%02X:%02X:%02X:%02X:%02X | Filter | %2d | %s | ---- | - | --- | -----------------\n",
355 descriptor
->macAddress
[0],
356 descriptor
->macAddress
[1],
357 descriptor
->macAddress
[2],
358 descriptor
->macAddress
[3],
359 descriptor
->macAddress
[4],
360 descriptor
->macAddress
[5],
361 descriptor
->recordData
.filteringData
.age
,
362 descriptor
->recordData
.filteringData
.staticEntry
? "static " : "dynamic");
364 else if (descriptor
->type
== IX_ETH_DB_WIFI_RECORD
)
366 if (descriptor
->recordData
.wifiData
.type
== IX_ETH_DB_WIFI_AP_TO_AP
)
368 /* gateway address present */
369 printf("%02X:%02X:%02X:%02X:%02X:%02X | WiFi | -- | AP=>AP | ---- | - | --- | %02X:%02X:%02X:%02X:%02X:%02X\n",
370 descriptor
->macAddress
[0],
371 descriptor
->macAddress
[1],
372 descriptor
->macAddress
[2],
373 descriptor
->macAddress
[3],
374 descriptor
->macAddress
[4],
375 descriptor
->macAddress
[5],
376 descriptor
->recordData
.wifiData
.gwMacAddress
[0],
377 descriptor
->recordData
.wifiData
.gwMacAddress
[1],
378 descriptor
->recordData
.wifiData
.gwMacAddress
[2],
379 descriptor
->recordData
.wifiData
.gwMacAddress
[3],
380 descriptor
->recordData
.wifiData
.gwMacAddress
[4],
381 descriptor
->recordData
.wifiData
.gwMacAddress
[5]);
386 printf("%02X:%02X:%02X:%02X:%02X:%02X | WiFi | -- | AP=>ST | ---- | - | --- | -- no gateway -- \n",
387 descriptor
->macAddress
[0],
388 descriptor
->macAddress
[1],
389 descriptor
->macAddress
[2],
390 descriptor
->macAddress
[3],
391 descriptor
->macAddress
[4],
392 descriptor
->macAddress
[5]);
395 else if (descriptor
->type
== IX_ETH_DB_FIREWALL_RECORD
)
397 printf("%02X:%02X:%02X:%02X:%02X:%02X | FW | -- | ------- | ---- | - | --- | -----------------\n",
398 descriptor
->macAddress
[0],
399 descriptor
->macAddress
[1],
400 descriptor
->macAddress
[2],
401 descriptor
->macAddress
[3],
402 descriptor
->macAddress
[4],
403 descriptor
->macAddress
[5]);
408 printf("invalid record filter\n");
413 * @brief displays the status, records and configuration information of a port
415 * @param portID ID of the port
416 * @param recordFilter record filter to display
421 void ixEthDBPortInfoShow(IxEthDBPortId portID
, IxEthDBRecordType recordFilter
)
423 PortInfo
*portInfo
= &ixEthDBPortInfo
[portID
];
424 UINT32 recordCount
= 0;
425 HashIterator iterator
;
426 IxEthDBStatus local_result
;
428 /* display port status */
429 printf("== Port ID %d ==\n", portID
);
431 /* display capabilities */
432 printf("- Capabilities: ");
434 if ((portInfo
->featureCapability
& IX_ETH_DB_LEARNING
) != 0)
436 printf("Learning (%s) ", ((portInfo
->featureStatus
& IX_ETH_DB_LEARNING
) != 0) ? "on" : "off");
439 if ((portInfo
->featureCapability
& IX_ETH_DB_VLAN_QOS
) != 0)
441 printf("VLAN/QoS (%s) ", ((portInfo
->featureStatus
& IX_ETH_DB_VLAN_QOS
) != 0) ? "on" : "off");
444 if ((portInfo
->featureCapability
& IX_ETH_DB_FIREWALL
) != 0)
446 printf("Firewall (%s) ", ((portInfo
->featureStatus
& IX_ETH_DB_FIREWALL
) != 0) ? "on" : "off");
449 if ((portInfo
->featureCapability
& IX_ETH_DB_WIFI_HEADER_CONVERSION
) != 0)
451 printf("WiFi (%s) ", ((portInfo
->featureStatus
& IX_ETH_DB_WIFI_HEADER_CONVERSION
) != 0) ? "on" : "off");
454 if ((portInfo
->featureCapability
& IX_ETH_DB_SPANNING_TREE_PROTOCOL
) != 0)
456 printf("STP (%s) ", ((portInfo
->featureStatus
& IX_ETH_DB_SPANNING_TREE_PROTOCOL
) != 0) ? "on" : "off");
462 ixEthDBDependencyPortMapShow(portID
, portInfo
->dependencyPortMap
);
464 /* NPE dynamic updates */
465 if (ixEthDBPortDefinitions
[portID
].type
== IX_ETH_NPE
)
467 printf(" - NPE dynamic update is %s\n", portInfo
->updateMethod
.updateEnabled
? "enabled" : "disabled");
471 printf(" - dynamic update disabled (not an NPE)\n");
474 if ((portInfo
->featureCapability
& IX_ETH_DB_WIFI_HEADER_CONVERSION
) != 0)
476 if ((portInfo
->featureStatus
& IX_ETH_DB_WIFI_HEADER_CONVERSION
) != 0)
478 /* WiFi header conversion */
479 if ((portInfo
->frameControlDurationID
485 + portInfo
->bbsid
[5]) == 0)
487 printf(" - WiFi header conversion not configured\n");
491 printf(" - WiFi header conversion: BBSID [%02X:%02X:%02X:%02X:%02X:%02X], Frame Control 0x%X, Duration/ID 0x%X\n",
498 portInfo
->frameControlDurationID
>> 16,
499 portInfo
->frameControlDurationID
& 0xFFFF);
504 printf(" - WiFi header conversion not enabled\n");
509 if ((portInfo
->featureCapability
& IX_ETH_DB_FIREWALL
) != 0)
511 if ((portInfo
->featureStatus
& IX_ETH_DB_FIREWALL
) != 0)
513 printf(" - Firewall is in %s-list mode\n", portInfo
->firewallMode
== IX_ETH_DB_FIREWALL_BLACK_LIST
? "black" : "white");
514 printf(" - Invalid source MAC address filtering is %s\n", portInfo
->srcAddressFilterEnabled
? "enabled" : "disabled");
518 printf(" - Firewall not enabled\n");
522 /* browse database if asked to display records */
523 if (recordFilter
!= IX_ETH_DB_NO_RECORD_TYPE
)
526 ixEthDBHeaderShow(recordFilter
);
528 BUSY_RETRY(ixEthDBInitHashIterator(&dbHashtable
, &iterator
));
530 while (IS_ITERATOR_VALID(&iterator
))
532 MacDescriptor
*descriptor
= (MacDescriptor
*) iterator
.node
->data
;
534 if (descriptor
->portID
== portID
&& (descriptor
->type
& recordFilter
) != 0)
539 ixEthDBRecordShow(descriptor
, recordFilter
);
542 /* move to the next record */
543 BUSY_RETRY_WITH_RESULT(ixEthDBIncrementHashIterator(&dbHashtable
, &iterator
), local_result
);
546 if (local_result
== IX_ETH_DB_BUSY
)
548 printf("EthDB (API): Error, database browser failed (no access), giving up\n");
552 printf("\nFound %d records\n\n", recordCount
);
557 * @brief displays a record header
559 * @param recordFilter record type filter
561 * This function displays a record header, depending on
562 * the given record type filter. It is useful when used
563 * in conjunction with ixEthDBRecordShow which will display
564 * record fields formatted for the header, provided the same
565 * record filter is used.
567 * @return IX_ETH_DB_SUCCESS if the operation completed
568 * successfully or IX_ETH_DB_INVALID_ARG if the recordFilter
569 * parameter is invalid or not supported
574 IxEthDBStatus
ixEthDBHeaderShow(IxEthDBRecordType recordFilter
)
576 if (recordFilter
== IX_ETH_DB_FILTERING_VLAN_RECORD
577 || recordFilter
== (IX_ETH_DB_FILTERING_RECORD
| IX_ETH_DB_FILTERING_VLAN_RECORD
))
579 /* display VLAN record header */
580 printf(" MAC address | Age | Type | VLAN ID | CFI | QoS class \n");
581 printf("___________________________________________________________________\n");
583 else if (recordFilter
== IX_ETH_DB_FILTERING_RECORD
)
585 /* display filtering record header */
586 printf(" MAC address | Age | Type \n");
587 printf("_______________________________________\n");
589 else if (recordFilter
== IX_ETH_DB_WIFI_RECORD
)
591 /* display WiFi record header */
592 printf(" MAC address | GW MAC address \n");
593 printf("_______________________________________\n");
595 else if (recordFilter
== IX_ETH_DB_FIREWALL_RECORD
)
597 /* display Firewall record header */
598 printf(" MAC address \n");
599 printf("__________________\n");
601 else if (recordFilter
== IX_ETH_DB_ALL_RECORD_TYPES
)
603 /* display composite record header */
604 printf(" MAC address | Record | Age| Type | VLAN |CFI| QoS | GW MAC address \n");
605 printf("_______________________________________________________________________________\n");
609 return IX_ETH_DB_INVALID_ARG
;
612 return IX_ETH_DB_SUCCESS
;
616 * @brief displays database information (records and port information)
618 * @param portID ID of the port to display (or IX_ETH_DB_ALL_PORTS for all the ports)
619 * @param recordFilter record filter (use IX_ETH_DB_NO_RECORD_TYPE to display only
622 * Note that this function is documented in the main component header
625 * @return IX_ETH_DB_SUCCESS if the operation completed successfully or
626 * an appropriate error code otherwise
630 IxEthDBStatus
ixEthDBFilteringDatabaseShowRecords(IxEthDBPortId portID
, IxEthDBRecordType recordFilter
)
632 IxEthDBPortId currentPort
;
633 BOOL showAllPorts
= (portID
== IX_ETH_DB_ALL_PORTS
);
635 IX_ETH_DB_CHECK_PORT_ALL(portID
);
637 printf("\nEthernet learning/filtering database: listing %d port(s)\n\n", showAllPorts
? (UINT32
) IX_ETH_DB_NUMBER_OF_PORTS
: 1);
639 currentPort
= showAllPorts
? 0 : portID
;
641 while (currentPort
!= IX_ETH_DB_NUMBER_OF_PORTS
)
643 /* display port info */
644 ixEthDBPortInfoShow(currentPort
, recordFilter
);
647 currentPort
= showAllPorts
? currentPort
+ 1 : IX_ETH_DB_NUMBER_OF_PORTS
;
650 return IX_ETH_DB_SUCCESS
;