[ONOS] Cherry picked from master 1.7 till june 10

Change-Id: Ide60fa5f6bd61fdfbc6ae050b78603cd5f1c78d9
diff --git a/apps/pce/app/src/main/java/org/onosproject/pce/cli/PceQueryPathCommand.java b/apps/pce/app/src/main/java/org/onosproject/pce/cli/PceQueryPathCommand.java
index 32323fa..284f776 100644
--- a/apps/pce/app/src/main/java/org/onosproject/pce/cli/PceQueryPathCommand.java
+++ b/apps/pce/app/src/main/java/org/onosproject/pce/cli/PceQueryPathCommand.java
@@ -35,6 +35,7 @@
         description = "Supports querying PCE path.")
 public class PceQueryPathCommand extends AbstractShellCommand {
     private final Logger log = getLogger(getClass());
+    public static final String COST_TYPE = "costType";
 
     @Option(name = "-i", aliases = "--id", description = "path-id", required = false,
             multiValued = false)
@@ -71,16 +72,16 @@
      * @param tunnel pce tunnel
      */
     void display(Tunnel tunnel) {
-        print("\npath-id            : %d \n" +
+        print("\npath-id            : %s \n" +
                 "source             : %s \n" +
                 "destination        : %s \n" +
-                "path-type          : %d \n" +
+                "path-type          : %s \n" +
                 "symbolic-path-name : %s \n" +
                 "constraints:            \n" +
-                "   cost            : %d \n" +
-                "   bandwidth       : %.2f",
+                "   cost            : %s \n" +
+                "   bandwidth       : %s",
                 tunnel.tunnelId().id(), tunnel.src().toString(), tunnel.dst().toString(),
-                tunnel.type(), tunnel.tunnelName(), tunnel.path().cost(),
+                tunnel.type().name(), tunnel.tunnelName(), tunnel.annotations().value(COST_TYPE),
                 tunnel.annotations().value(AnnotationKeys.BANDWIDTH));
     }
 }
diff --git a/apps/pce/app/src/main/java/org/onosproject/pce/cli/PceSetupPathCommand.java b/apps/pce/app/src/main/java/org/onosproject/pce/cli/PceSetupPathCommand.java
index a14e6e1..d7e514b 100644
--- a/apps/pce/app/src/main/java/org/onosproject/pce/cli/PceSetupPathCommand.java
+++ b/apps/pce/app/src/main/java/org/onosproject/pce/cli/PceSetupPathCommand.java
@@ -86,9 +86,10 @@
         LspType lspType = LspType.values()[type];
 
         // Add bandwidth
-        // bandwidth default data rate unit is in BPS
+        // bandwidth default data rate unit is in MBPS, since bandwidth value in network config
+        //stored in MPBS
         if (bandwidth != 0.0) {
-            listConstrnt.add(BandwidthConstraint.of(bandwidth, DataRateUnit.valueOf("BPS")));
+            listConstrnt.add(BandwidthConstraint.of(bandwidth, DataRateUnit.valueOf("MBPS")));
         }
 
         // Add cost
diff --git a/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PceManager.java b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PceManager.java
index 2e148db..41e14dd 100644
--- a/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PceManager.java
+++ b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PceManager.java
@@ -893,9 +893,7 @@
 
         // Check whether device has SR-TE Capability
         if (cfg.labelStackCap()) {
-            if (!srTeHandler.allocateNodeLabel(deviceId, lsrId)) {
-                log.error("Node label allocation for a device id {} has failed.", deviceId.toString());
-            }
+            srTeHandler.allocateNodeLabel(deviceId, lsrId);
         }
     }
 
@@ -974,10 +972,7 @@
 
         // Check whether device has SR-TE Capability
         if (cfg.labelStackCap()) {
-            if (!srTeHandler.allocateAdjacencyLabel(link)) {
-                log.error("Unable to allocate adjacency label for a link {}.", link.toString());
-                return;
-            }
+            srTeHandler.allocateAdjacencyLabel(link);
         }
 
         return;
@@ -1209,16 +1204,13 @@
                 if (cfg.labelStackCap()) {
                     if (mastershipService.getLocalRole(deviceId) == MastershipRole.MASTER) {
                         // Allocate node-label
-                        if (!srTeHandler.allocateNodeLabel(deviceId, lsrId)) {
-                            log.error("Node label allocation for a device id {} has failed.", deviceId.toString());
-                        }
+                        srTeHandler.allocateNodeLabel(deviceId, lsrId);
 
                         // Allocate adjacency label to links which are
                         // originated from this specific device id
                         Set<Link> links = linkService.getDeviceEgressLinks(deviceId);
                         for (Link link : links) {
                             if (!srTeHandler.allocateAdjacencyLabel(link)) {
-                                log.debug("Unable to allocate adjacency labels for a link {}.", link.toString());
                                 return;
                             }
                         }
@@ -1240,40 +1232,42 @@
             return false;
         }
 
-        Map<DeviceId, LabelResourceId> globalNodeLabelMap = pceStore.getGlobalNodeLabels();
+        if (pceStore.getGlobalNodeLabel(deviceId) != null) {
+            Map<DeviceId, LabelResourceId> globalNodeLabelMap = pceStore.getGlobalNodeLabels();
 
-        for (Entry<DeviceId, LabelResourceId> entry : globalNodeLabelMap.entrySet()) {
+            for (Entry<DeviceId, LabelResourceId> entry : globalNodeLabelMap.entrySet()) {
 
-            // Convert from DeviceId to TunnelEndPoint
-            Device srcDevice = deviceService.getDevice(entry.getKey());
+                // Convert from DeviceId to TunnelEndPoint
+                Device srcDevice = deviceService.getDevice(entry.getKey());
 
-            /*
-             * If there is a slight difference in timing such that if device subsystem has removed the device but PCE
-             * store still has it, just ignore such devices.
-             */
-            if (srcDevice == null) {
-                continue;
+                /*
+                 * If there is a slight difference in timing such that if device subsystem has removed the device but
+                 * PCE store still has it, just ignore such devices.
+                 */
+                if (srcDevice == null) {
+                    continue;
+                }
+
+                String srcLsrId = srcDevice.annotations().value(LSRID);
+                if (srcLsrId == null) {
+                    continue;
+                }
+
+                srTeHandler.advertiseNodeLabelRule(deviceId,
+                                                   entry.getValue(),
+                                                   IpPrefix.valueOf(IpAddress.valueOf(srcLsrId), PREFIX_LENGTH),
+                                                   Objective.Operation.ADD, false);
             }
 
-            String srcLsrId = srcDevice.annotations().value(LSRID);
-            if (srcLsrId == null) {
-                continue;
-            }
-
-            srTeHandler.advertiseNodeLabelRule(deviceId,
-                                               entry.getValue(),
-                                               IpPrefix.valueOf(IpAddress.valueOf(srcLsrId), PREFIX_LENGTH),
-                                               Objective.Operation.ADD, false);
-        }
-
-        Map<Link, LabelResourceId> adjLabelMap = pceStore.getAdjLabels();
-        for (Entry<Link, LabelResourceId> entry : adjLabelMap.entrySet()) {
-            if (entry.getKey().src().deviceId().equals(deviceId)) {
-                srTeHandler.installAdjLabelRule(deviceId,
-                                                entry.getValue(),
-                                                entry.getKey().src().port(),
-                                                entry.getKey().dst().port(),
-                                                Objective.Operation.ADD);
+            Map<Link, LabelResourceId> adjLabelMap = pceStore.getAdjLabels();
+            for (Entry<Link, LabelResourceId> entry : adjLabelMap.entrySet()) {
+                if (entry.getKey().src().deviceId().equals(deviceId)) {
+                    srTeHandler.installAdjLabelRule(deviceId,
+                                                    entry.getValue(),
+                                                    entry.getKey().src().port(),
+                                                    entry.getKey().dst().port(),
+                                                    Objective.Operation.ADD);
+                }
             }
         }
 
@@ -1281,6 +1275,9 @@
                                            LabelResourceId.labelResourceId(0),
                                            IpPrefix.valueOf(END_OF_SYNC_IP_PREFIX),
                                            Objective.Operation.ADD, true);
+
+        log.debug("End of label DB sync for device {}", deviceId);
+
         if (mastershipService.getLocalRole(specificDevice.id()) == MastershipRole.MASTER) {
             // Allocate node-label to this specific device.
             allocateNodeLabel(specificDevice);
@@ -1304,6 +1301,7 @@
         public void process(PacketContext context) {
             // Stop processing if the packet has been handled, since we
             // can't do any more to it.
+            log.debug("Received trigger for label DB sync.");
             if (context.isHandled()) {
                 return;
             }
diff --git a/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PceccSrTeBeHandler.java b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PceccSrTeBeHandler.java
index c760bc1..63eed1b 100644
--- a/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PceccSrTeBeHandler.java
+++ b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PceccSrTeBeHandler.java
@@ -28,7 +28,6 @@
 import org.onlab.packet.IpAddress;
 import org.onlab.packet.IpPrefix;
 import org.onlab.packet.MplsLabel;
-import org.onlab.packet.TpPort;
 import org.onosproject.core.ApplicationId;
 import org.onosproject.incubator.net.resource.label.DefaultLabelResource;
 import org.onosproject.incubator.net.resource.label.LabelResource;
@@ -184,7 +183,7 @@
 
         // Check whether node-label was already configured for this specific device.
         if (pceStore.getGlobalNodeLabel(specificDeviceId) != null) {
-            log.error("Node label was already configured for device {}.", specificDeviceId.toString());
+            log.debug("Node label was already configured for device {}.", specificDeviceId.toString());
             return false;
         }
 
@@ -228,12 +227,15 @@
 
             // Push to device
             // Push label information of specificDeviceId to otherDevId in list and vice versa.
-            advertiseNodeLabelRule(otherDevId, specificLabelId,
-                                   IpPrefix.valueOf(IpAddress.valueOf(specificLsrId), PREFIX_LENGTH),
-                                   Objective.Operation.ADD, false);
-            advertiseNodeLabelRule(specificDeviceId, otherLabelId,
-                                   IpPrefix.valueOf(IpAddress.valueOf(otherLsrId), PREFIX_LENGTH),
-                                   Objective.Operation.ADD, false);
+            if (!otherDevId.equals(specificDeviceId)) {
+                advertiseNodeLabelRule(otherDevId, specificLabelId,
+                                       IpPrefix.valueOf(IpAddress.valueOf(specificLsrId), PREFIX_LENGTH),
+                                       Objective.Operation.ADD, false);
+
+                advertiseNodeLabelRule(specificDeviceId, otherLabelId,
+                                       IpPrefix.valueOf(IpAddress.valueOf(otherLsrId), PREFIX_LENGTH),
+                                       Objective.Operation.ADD, false);
+            }
         }
 
         return true;
@@ -519,8 +521,8 @@
         TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
 
         selectorBuilder.matchMplsLabel(MplsLabel.mplsLabel(labelId.id().intValue()));
-        selectorBuilder.matchTcpSrc(TpPort.tpPort((int) srcPortNum.toLong()));
-        selectorBuilder.matchTcpDst(TpPort.tpPort((int) dstPortNum.toLong()));
+        selectorBuilder.matchIPSrc(IpPrefix.valueOf((int) srcPortNum.toLong(), 32));
+        selectorBuilder.matchIPDst(IpPrefix.valueOf((int) dstPortNum.toLong(), 32));
 
         TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
 
diff --git a/apps/pce/app/src/main/java/org/onosproject/pce/pcestore/DistributedPceStore.java b/apps/pce/app/src/main/java/org/onosproject/pce/pcestore/DistributedPceStore.java
index f692a62..6afdb30 100644
--- a/apps/pce/app/src/main/java/org/onosproject/pce/pcestore/DistributedPceStore.java
+++ b/apps/pce/app/src/main/java/org/onosproject/pce/pcestore/DistributedPceStore.java
@@ -38,6 +38,7 @@
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.Link;
 import org.onosproject.net.resource.ResourceConsumer;
+import org.onosproject.pce.pceservice.constraint.CapabilityConstraint;
 import org.onosproject.pce.pceservice.constraint.CostConstraint;
 import org.onosproject.pce.pceservice.TunnelConsumerId;
 import org.onosproject.pce.pceservice.LspType;
@@ -132,6 +133,8 @@
                                           CostConstraint.class,
                                           CostConstraint.Type.class,
                                           BandwidthConstraint.class,
+                                          CapabilityConstraint.class,
+                                          CapabilityConstraint.CapabilityType.class,
                                           LspType.class)
                                 .build()))
 
@@ -216,19 +219,19 @@
     @Override
     public LabelResourceId getGlobalNodeLabel(DeviceId id) {
         checkNotNull(id, DEVICE_ID_NULL);
-        return globalNodeLabelMap.get(id).value();
+        return globalNodeLabelMap.get(id) == null ? null : globalNodeLabelMap.get(id).value();
     }
 
     @Override
     public LabelResourceId getAdjLabel(Link link) {
         checkNotNull(link, LINK_NULL);
-        return adjLabelMap.get(link).value();
+        return adjLabelMap.get(link) == null ? null : adjLabelMap.get(link).value();
     }
 
     @Override
     public PceccTunnelInfo getTunnelInfo(TunnelId tunnelId) {
         checkNotNull(tunnelId, TUNNEL_ID_NULL);
-        return tunnelInfoMap.get(tunnelId).value();
+        return tunnelInfoMap.get(tunnelId) == null ? null : tunnelInfoMap.get(tunnelId).value();
     }
 
     @Override
diff --git a/apps/pce/pceweb/src/main/java/org/onosproject/pceweb/PceWebTopovMessageHandler.java b/apps/pce/pceweb/src/main/java/org/onosproject/pceweb/PceWebTopovMessageHandler.java
index 95e9f1f..72f0118 100644
--- a/apps/pce/pceweb/src/main/java/org/onosproject/pceweb/PceWebTopovMessageHandler.java
+++ b/apps/pce/pceweb/src/main/java/org/onosproject/pceweb/PceWebTopovMessageHandler.java
@@ -431,7 +431,6 @@
                 lspTypeVal = LspType.SR_WITHOUT_SIGNALLING;
                 break;
             default:
-                log.error("Invalid LSP type");
                 break;
         }
 
@@ -539,7 +538,6 @@
             costTypeVal = CostConstraint.Type.TE_COST;
             break;
         default:
-            log.error("Invalid cost type");
             break;
         }
 
@@ -660,12 +658,17 @@
         tunnelSet = tunnelService.queryTunnel(MPLS);
         for (Tunnel tunnel : tunnelSet) {
             if (tunnel.path() == null) {
-                log.info("path does not exist");
+                log.error("path does not exist");
                 return;
             }
             paths.add(tunnel.path());
         }
 
+        if (tunnelSet.size() == 0) {
+            log.warn("Tunnel does not exist");
+            return;
+        }
+
         ImmutableSet.Builder<Link> builder = ImmutableSet.builder();
         allPathLinks = buildPaths(builder).build();
         hilightAndSendPaths();
diff --git a/apps/pce/pceweb/src/main/java/org/onosproject/pceweb/PceWebTopovOverlay.java b/apps/pce/pceweb/src/main/java/org/onosproject/pceweb/PceWebTopovOverlay.java
index 41f3243..044b7a2 100644
--- a/apps/pce/pceweb/src/main/java/org/onosproject/pceweb/PceWebTopovOverlay.java
+++ b/apps/pce/pceweb/src/main/java/org/onosproject/pceweb/PceWebTopovOverlay.java
@@ -17,18 +17,28 @@
 package org.onosproject.pceweb;
 
 
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.onlab.util.Bandwidth;
 import org.onosproject.net.AnnotationKeys;
 import org.onosproject.net.Annotations;
 import org.onosproject.net.Device;
 import org.onosproject.net.DeviceId;
+import org.onosproject.net.Link;
 import org.onosproject.ui.UiTopoOverlay;
 import org.onosproject.ui.topo.ButtonId;
 import org.onosproject.ui.topo.PropertyPanel;
 import org.onosproject.net.HostId;
 import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.link.LinkEvent;
+import org.onosproject.net.resource.ContinuousResource;
+import org.onosproject.net.resource.DiscreteResource;
+import org.onosproject.net.resource.Resource;
+import org.onosproject.net.resource.ResourceService;
+import org.onosproject.net.resource.Resources;
 import org.onosproject.ui.topo.TopoConstants.CoreButtons;
-
-import static org.onosproject.ui.topo.TopoConstants.Properties.*;
 import org.onosproject.cli.AbstractShellCommand;
 
 /**
@@ -42,7 +52,9 @@
 
     public static final String AS_NUMBER = "asNumber";
     public static final String DOMAIN_IDENTIFIER = "domainIdentifier";
-    public static final String ROUTING_UNIVERSE = "routingUniverse";
+    public static final String ABR_BIT = "abrBit";
+    public static final String ASBR_BIT = "externalBit";
+    public static final String TE_METRIC = "teCost";
 
     private static final ButtonId SRC_BUTTON = new ButtonId("src");
     private static final ButtonId DST_BUTTON = new ButtonId("dst");
@@ -77,34 +89,75 @@
          if (deviceService != null) {
 
             Device device = deviceService.getDevice(deviceId);
-            Annotations annot = device.annotations();
+            Annotations annots = device.annotations();
 
-            String routerId = annot.value(AnnotationKeys.ROUTER_ID);
-            String type = annot.value(AnnotationKeys.TYPE);
-            String asNumber = annot.value(AS_NUMBER);
-            String domain = annot.value(DOMAIN_IDENTIFIER);
-            String routingUnverse = annot.value(ROUTING_UNIVERSE);
+            String routerId = annots.value(AnnotationKeys.ROUTER_ID);
+            String type = annots.value(AnnotationKeys.TYPE);
+            String asNumber = annots.value(AS_NUMBER);
+            String domain = annots.value(DOMAIN_IDENTIFIER);
+            String abrStatus = annots.value(ABR_BIT);
+            String asbrStatus = annots.value(ASBR_BIT);
 
             if (type != null) {
                 pp.addProp("Type", type);
             }
-            /* TBD: Router ID need to print
+
             if (routerId != null) {
                 pp.addProp("Router-ID", routerId);
-            } */
-            if (routingUnverse != null) {
-                pp.addProp("Routing Universe", routingUnverse);
             }
+
             if (asNumber != null) {
                 pp.addProp("AS Number", asNumber);
             }
+
             if (domain != null) {
                 pp.addProp("Domain ID", domain);
             }
+
+            if (abrStatus != null) {
+                pp.addProp("ABR Role", abrStatus);
+            }
+
+            if (asbrStatus != null) {
+                pp.addProp("ASBR Role", asbrStatus);
+            }
         }
     }
 
     @Override
+    public Map<String, String> additionalLinkData(LinkEvent event) {
+        Map<String, String> map = new HashMap<>();
+        Link link = event.subject();
+
+        map.put("Src port", link.src().port().toString());
+        map.put("Dst port", link.dst().port().toString());
+        map.put("Te metric", link.annotations().value(TE_METRIC));
+
+        ResourceService resService = AbstractShellCommand.get(ResourceService.class);
+        DiscreteResource devResource = Resources.discrete(link.src().deviceId(), link.src().port()).resource();
+        if (resService == null) {
+            log.warn("resource service does not exist ");
+            return map;
+        }
+
+        if (devResource == null) {
+            log.warn("Device resources does not exist ");
+            return map;
+        }
+        Set<Resource> resources = resService.getAvailableResources(devResource.id(), Bandwidth.class);
+        if (resources.isEmpty()) {
+            log.warn("Bandwidth resources does not exist ");
+            return map;
+        }
+
+        if (resources.iterator().next() instanceof ContinuousResource) {
+            map.put("Bandwidth", ((ContinuousResource) resources.iterator().next()).toString());
+        }
+
+        return map;
+    }
+
+    @Override
     public void modifyHostDetails(PropertyPanel pp, HostId hostId) {
         pp.addButton(SRC_BUTTON).addButton(DST_BUTTON);
     }
diff --git a/apps/pce/pceweb/src/main/resources/app/view/pcewebTopov/pcewebTopovDemo.js b/apps/pce/pceweb/src/main/resources/app/view/pcewebTopov/pcewebTopovDemo.js
index e16e15b..586ebea 100644
--- a/apps/pce/pceweb/src/main/resources/app/view/pcewebTopov/pcewebTopovDemo.js
+++ b/apps/pce/pceweb/src/main/resources/app/view/pcewebTopov/pcewebTopovDemo.js
@@ -96,9 +96,9 @@
         addAttribute('pce-cost-type-valname', 'pce-cost-type-te', 'TE', 'radio');
         //Add the LSP type related inputs.
         addAttribute('pce-lsp-type-name', 'pce-lsp-type', 'Lsp Type', 'checkbox');
-        addAttribute('pce-lsp-type-valname', 'pce-lsp-type-cr', 'WITH SIGNALLING', 'radio');
-        addAttribute('pce-lsp-type-valname', 'pce-lsp-type-srbe', 'WITHOUT SR WITHOUT SIGNALLING', 'radio');
-        addAttribute('pce-lsp-type-valname', 'pce-lsp-type-srte', 'WITH SR WITHOUT SIGNALLING', 'radio');
+        addAttribute('pce-lsp-type-valname', 'pce-lsp-type-cr', 'With signalling', 'radio');
+        addAttribute('pce-lsp-type-valname', 'pce-lsp-type-srbe', 'Without SR without signalling', 'radio');
+        addAttribute('pce-lsp-type-valname', 'pce-lsp-type-srte', 'With SR without signalling', 'radio');
         //Add the tunnel name
         addAttribute('pce-tunnel-name', 'pce-tunnel-name-id', 'Tunnel Name', 'text');
 
@@ -182,12 +182,12 @@
         return content;
     }
 
-    function isChecked(viewId) {
-        return d3.select('#' + viewId).property('checked');
+    function isChecked(cboxId) {
+        return d3.select('#' + cboxId).property('checked');
     }
 
-    function getCheckedValue(viewId) {
-        return d3.select('#' + viewId).property('value');
+    function getCheckedValue(cboxId) {
+        return d3.select('#' + cboxId).property('value');
     }
 
     function showTunnelInformation(data) {
@@ -198,25 +198,19 @@
             var tdString = '' ;
             tunnelNameData.a.forEach( function (val, idx) {
                 var tunnelName = isChecked('tunnel-id-'+idx);
-                if (tunnelName)
-                {
+                if (tunnelName) {
                     tdString = val;
                 }
             } );
 
-            if (tdString) {
-                constraintsUpdateDialog(tdString);
-            } else {
-                $log.debug("No tunnel id is selected.");
-            }
-
+            constraintsUpdateDialog(tdString);
             $log.debug('Dialog OK button clicked');
         }
 
         tds.openDialog()
             .setTitle('Available LSPs with selected device')
             .addContent(createUserTextUpdate(data))
-            .addOkChained(dOkUpdate, 'GOTO Selection of constraints')
+            .addOkChained(dOkUpdate, 'OK')
             .addCancel(dClose, 'Close')
             .bindKeys();
     }
@@ -266,7 +260,7 @@
             .setTitle('Select constraints for update path')
             .addContent(createUserTextUpdatePathEvent())
             .addCancel()
-            .addOk(dOkUpdateEvent, 'Update Path')     // NOTE: NOT the "chained" version!
+            .addOk(dOkUpdateEvent, 'OK')     // NOTE: NOT the "chained" version!
             .bindKeys();
 
     }
@@ -278,7 +272,7 @@
         tds.openDialog()
             .setTitle('Available Tunnels for remove')
             .addContent(createUserTextRemove(data))
-            .addOk(dOkRemove, 'Remove')
+            .addOk(dOkRemove, 'OK')
             .addCancel(dClose, 'Close')
             .bindKeys();
     }
diff --git a/apps/pce/pceweb/src/main/resources/app/view/pcewebTopov/pcewebTopovOverlay.js b/apps/pce/pceweb/src/main/resources/app/view/pcewebTopov/pcewebTopovOverlay.js
index 4ad40a0..72dd1ef 100644
--- a/apps/pce/pceweb/src/main/resources/app/view/pcewebTopov/pcewebTopovOverlay.js
+++ b/apps/pce/pceweb/src/main/resources/app/view/pcewebTopov/pcewebTopovOverlay.js
@@ -168,6 +168,29 @@
             },
             multi: function (selectOrder) {
                 selectionCallback(selectOrder);
+            },
+            modifylinkdata: function (data, extra) {
+                $log.debug("Modify link data", data, extra);
+
+                function sep() {
+                    data.propOrder.push('-');
+                }
+
+                function add(key) {
+                    var val = extra[key];
+                    if (val !== undefined) {
+                        data.propOrder.push(key);
+                        data.props[key] = val;
+                    }
+                }
+
+                sep();
+                add('Src port');
+                add('Dst port');
+                add('Te metric');
+                add('Bandwidth');
+
+                return data;
             }
         }
     };