diff --git a/doc/API/API-Docs.md b/doc/API/API-Docs.md
index 185349b95..b23339ee8 100644
--- a/doc/API/API-Docs.md
+++ b/doc/API/API-Docs.md
@@ -13,6 +13,7 @@
- [`get_graphs`](#api-route-5)
- [`get_graph_generic_by_hostname`](#api-route-6)
- [`get_port_graphs`](#api-route-7)
+ - [`get_port_stack`](#api-route-29)
- [`get_components`](#api-route-25)
- [`add_components`](#api-route-26)
- [`edit_components`](#api-route-27)
@@ -275,6 +276,47 @@ Output:
}
```
+### Function: `get_port_stack` [`top`](#top)
+
+Get a list of port mappings for a device. This is useful for showing physical ports that are in a virtual port-channel.
+
+Route: /api/v0/devices/:hostname/port_stack
+
+- hostname can be either the device hostname or id
+
+Input:
+
+ - valid_mappings: Filter the result by only showing valid mappings ("0" values not shown).
+
+Example:
+```curl
+curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/port_stack?valid_mappings
+```
+
+Output:
+
+```text
+{
+ "status": "ok",
+ "err-msg": "",
+ "count": 2,
+ "mappings": [
+ {
+ "device_id": "3742",
+ "port_id_high": "1001000",
+ "port_id_low": "51001",
+ "ifStackStatus": "active"
+ },
+ {
+ "device_id": "3742",
+ "port_id_high": "1001000",
+ "port_id_low": "52001",
+ "ifStackStatus": "active"
+ }
+ ]
+}
+```
+
### Function: `get_components` [`top`](#top)
Get a list of components for a particular device.
diff --git a/html/includes/api_functions.inc.php b/html/includes/api_functions.inc.php
index 004138f16..9a2629890 100644
--- a/html/includes/api_functions.inc.php
+++ b/html/includes/api_functions.inc.php
@@ -726,10 +726,15 @@ function get_port_stack() {
$app = \Slim\Slim::getInstance();
$router = $app->router()->getCurrentRoute()->getParams();
$hostname = $router['hostname'];
-
// use hostname as device_id if it's all digits
$device_id = ctype_digit($hostname) ? $hostname : getidbyname($hostname);
- $mappings = dbFetchRows("SELECT * FROM `ports_stack` WHERE `device_id` = ? AND `ifStackStatus` = 'active' ORDER BY `port_id_high` ASC", array($device_id));
+
+ if (isset($_GET['valid_mappings'])) {
+ $mappings = dbFetchRows("SELECT * FROM `ports_stack` WHERE (`device_id` = ? AND `ifStackStatus` = 'active' AND (`port_id_high` != '0' AND `port_id_low` != '0')) ORDER BY `port_id_high` ASC", array($device_id));
+ } else {
+ $mappings = dbFetchRows("SELECT * FROM `ports_stack` WHERE `device_id` = ? AND `ifStackStatus` = 'active' ORDER BY `port_id_high` ASC", array($device_id));
+ }
+
$total_mappings = count($mappings);
$output = array(
'status' => 'ok',