Repository: napalm-automation-community/napalm-s350

Issue:
parsing show lldp neighbors
I am working my way through the development branch and came across the parser for lldp neigbors. I don't think it works reliably. I have seen the case that both the system name and the port ID can be wrapped.

Examples:

```
switchf5bcdb#show lldp neighbors

System capability legend:
B - Bridge; R - Router; W - Wlan Access Point; T - telephone;
D - DOCSIS Cable Device; H - Host; r - Repeater;
TP - Two Ports MAC Relay; S - S-VLAN; C - C-VLAN; O - Other

  Port        Device ID        Port ID       System Name    Capabilities  TTL
--------- ----------------- ------------- ----------------- ------------ -----
gi7       00:a5:bf:c2:3c:f0      gi8        switchc23cf0        B, R      91
gi8       f2:18:98:43:be:9b 9c:eb:e8:52:b    iai-sti006         B, W      115
                            d:7c
```

```
System capability legend:
B - Bridge; R - Router; W - Wlan Access Point; T - telephone;
D - DOCSIS Cable Device; H - Host; r - Repeater;
TP - Two Ports MAC Relay; S - S-VLAN; C - C-VLAN; O - Other

  Port        Device ID          Port ID         System Name    Capabilities  TTL
--------- ----------------- ----------------- ----------------- ------------ -----
te1/0/1   a0:f8:49:f2:4b:b6     te1/0/22       xx-rackswitch9      B, R      100
te1/0/2   a0:f8:49:f2:4b:b6     te2/0/22       xx-rackswitch9      B, R      105
te1/0/22  00:25:45:03:a5:c0       Te1/2       scn-0123-r004-3.t     B, R      98
                                              mn.xxx.xxx.xxx
```

Lines: https://github.com/napalm-automation-community/napalm-s350/blob/657bcc570ddcb0115e017fc2819aa38f95bde177/napalm_s350/s350.py#L360-L396

Discussion:

Patch:
diff --git a/napalm_s350/s350.py b/napalm_s350/s350.py
index 23c371a..206249f 100644
--- a/napalm_s350/s350.py
+++ b/napalm_s350/s350.py
@@ -406,14 +406,17 @@ class S350Driver(NetworkDriver):
                 match = re.match(r'^--------- -+ .*$', line)
                 if match:
                     header = False
+                    fields_end = self._get_lldp_neighbors_fields_end(line)
                 continue
 
-            line_elems = line.split()
+            line_elems = self._get_lldp_neighbors_line_to_fields(line, fields_end)
 
-            # long system name owerflow to the other line
-            if len(line_elems) == 1:
-                # complete remote name
-                remote_name = remote_name + line_elems[0]
+            # info owerflow to the other line
+            if     line_elems[0] == '' or line_elems[4] == '' or line_elems[5] == '' :
+                # complete owerflown fields
+                local_port  = local_port  + line_elems[0]
+                remote_port = remote_port + line_elems[2]
+                remote_name = remote_name + line_elems[3]
                 # then reuse old values na rewrite previous entry
             else:
                 local_port = line_elems[0]
@@ -429,6 +432,26 @@ class S350Driver(NetworkDriver):
 
         return neighbors
 
+    def _get_lldp_neighbors_line_to_fields(self, line, fields_end):
+        """ dynamic fields lenghts """
+        line_elems={}
+        index=0
+        f_start=0
+        for f_end in fields_end:
+            line_elems[index] = line[f_start:f_end].strip()
+            index += 1
+            f_start = f_end
+        return line_elems
+
+    def _get_lldp_neighbors_fields_end(self, dashline):
+        """ fields length are diferent device to device, detect them on horizontal lin """
+
+        fields_end=[m.start() for m in re.finditer(' ', dashline)]
+        #fields_position.insert(0,0)
+        fields_end.append(len(dashline))
+
+        return fields_end
+
     def _get_lldp_line_value(self, line):
         """
         Safe-ish method to get the value from an 'lldp neighbors $IF' line.


Test patch:
diff --git a/test/unit/mocked_data/test_get_lldp_neighbors/SG350X-48P-K9-long_systemname/expected_result.json b/test/unit/mocked_data/test_get_lldp_neighbors/SG350X-48P-K9-long_systemname/expected_result.json
index 942f033..591a9c5 100644
--- a/test/unit/mocked_data/test_get_lldp_neighbors/SG350X-48P-K9-long_systemname/expected_result.json
+++ b/test/unit/mocked_data/test_get_lldp_neighbors/SG350X-48P-K9-long_systemname/expected_result.json
@@ -4,7 +4,7 @@
         "port" : "74:ac:aa:ff:1a:5f"
       } ],
   "gi1/0/35" : [ { 
-        "hostname" : "O",
+        "hostname" : "",
         "port" : "34:e6:aa:ff:53:a8"
       } ],
   "te1/0/1" : [ { 
diff --git a/test/unit/mocked_data/test_get_lldp_neighbors/SG350X-48P-K9/expected_result.json b/test/unit/mocked_data/test_get_lldp_neighbors/SG350X-48P-K9/expected_result.json
index 51fea79..34b31f9 100644
--- a/test/unit/mocked_data/test_get_lldp_neighbors/SG350X-48P-K9/expected_result.json
+++ b/test/unit/mocked_data/test_get_lldp_neighbors/SG350X-48P-K9/expected_result.json
@@ -4,7 +4,7 @@
         "port" : "74:ac:aa:ff:1a:5f"
       } ],
   "gi1/0/35" : [ { 
-        "hostname" : "O",
+        "hostname" : "",
         "port" : "34:e6:aa:ff:53:a8"
       } ],
   "te1/0/1" : [ { 
diff --git a/test/unit/mocked_data/test_get_lldp_neighbors/SG3xx-long_port_and_sysname/expected_result.json b/test/unit/mocked_data/test_get_lldp_neighbors/SG3xx-long_port_and_sysname/expected_result.json
new file mode 100644
index 0000000..5683619
--- /dev/null
+++ b/test/unit/mocked_data/test_get_lldp_neighbors/SG3xx-long_port_and_sysname/expected_result.json
@@ -0,0 +1,10 @@
+{ 
+  "gi7" : [ { 
+        "hostname" : "switchc23cf0",
+        "port" : "gi8"
+      } ],
+  "gi8" : [ { 
+        "hostname" : "iai-sti0067.example.net",
+        "port" : "9c:eb:e8:52:bd:7c"
+      } ]
+}
diff --git a/test/unit/mocked_data/test_get_lldp_neighbors/SG3xx-long_port_and_sysname/show_lldp_neighbors.txt b/test/unit/mocked_data/test_get_lldp_neighbors/SG3xx-long_port_and_sysname/show_lldp_neighbors.txt
new file mode 100644
index 0000000..7da8dbe
--- /dev/null
+++ b/test/unit/mocked_data/test_get_lldp_neighbors/SG3xx-long_port_and_sysname/show_lldp_neighbors.txt
@@ -0,0 +1,12 @@
+
+System capability legend:
+B - Bridge; R - Router; W - Wlan Access Point; T - telephone;
+D - DOCSIS Cable Device; H - Host; r - Repeater;
+TP - Two Ports MAC Relay; S - S-VLAN; C - C-VLAN; O - Other
+
+  Port        Device ID        Port ID       System Name    Capabilities  TTL
+--------- ----------------- ------------- ----------------- ------------ -----
+gi7       00:a5:bf:c2:3c:f0      gi8        switchc23cf0        B, R      91
+gi8       f2:18:98:43:be:9b 9c:eb:e8:52:b iai-sti0067.examp     B, W      115
+                            d:7c          le.net
+
diff --git a/test/unit/mocked_data/test_get_lldp_neighbors/SG3xx-long_port_id/expected_result.json b/test/unit/mocked_data/test_get_lldp_neighbors/SG3xx-long_port_id/expected_result.json
new file mode 100644
index 0000000..8df5b44
--- /dev/null
+++ b/test/unit/mocked_data/test_get_lldp_neighbors/SG3xx-long_port_id/expected_result.json
@@ -0,0 +1,1 @@
+{"gi7": [{"hostname": "switchc23cf0", "port": "gi8"}], "gi8": [{"hostname": "iai-sti006", "port": "9c:eb:e8:52:bd:7c"}]}
diff --git a/test/unit/mocked_data/test_get_lldp_neighbors/SG3xx-long_port_id/show_lldp_neighbors.txt b/test/unit/mocked_data/test_get_lldp_neighbors/SG3xx-long_port_id/show_lldp_neighbors.txt
new file mode 100644
index 0000000..cc12440
--- /dev/null
+++ b/test/unit/mocked_data/test_get_lldp_neighbors/SG3xx-long_port_id/show_lldp_neighbors.txt
@@ -0,0 +1,12 @@
+
+System capability legend:
+B - Bridge; R - Router; W - Wlan Access Point; T - telephone;
+D - DOCSIS Cable Device; H - Host; r - Repeater;
+TP - Two Ports MAC Relay; S - S-VLAN; C - C-VLAN; O - Other
+
+  Port        Device ID        Port ID       System Name    Capabilities  TTL
+--------- ----------------- ------------- ----------------- ------------ -----
+gi7       00:a5:bf:c2:3c:f0      gi8        switchc23cf0        B, R      91
+gi8       f2:18:98:43:be:9b 9c:eb:e8:52:b    iai-sti006         B, W      115
+                            d:7c
+