Saurav Das
Committed by Ray Milkey

Changes include:

      bug fix for host IP and MAC flows not being generated sometimes in multi-controller scenarios
      bug fix for filtering objectives not being sent sometimes when ports become available later
      npe fixes in ofdpa driver for cases where selectors or treatments may not be available
      new cli command to manually trigger routing and rule population
      portstats option on cli to display only those ports with non-zero stats
      group cli command tab completion displays choices in lower case (similar to flows)
      segment routing cli commands now start with sr-

Change-Id: Idcd641882d180acbd304e5560ed3483b5a943f96
Showing 20 changed files with 181 additions and 24 deletions
...@@ -32,6 +32,9 @@ import java.util.ArrayList; ...@@ -32,6 +32,9 @@ import java.util.ArrayList;
32 import java.util.HashMap; 32 import java.util.HashMap;
33 import java.util.HashSet; 33 import java.util.HashSet;
34 import java.util.Set; 34 import java.util.Set;
35 +import java.util.concurrent.Executors;
36 +import java.util.concurrent.ScheduledExecutorService;
37 +import java.util.concurrent.TimeUnit;
35 import java.util.concurrent.locks.Lock; 38 import java.util.concurrent.locks.Lock;
36 import java.util.concurrent.locks.ReentrantLock; 39 import java.util.concurrent.locks.ReentrantLock;
37 40
...@@ -53,6 +56,8 @@ public class DefaultRoutingHandler { ...@@ -53,6 +56,8 @@ public class DefaultRoutingHandler {
53 private DeviceConfiguration config; 56 private DeviceConfiguration config;
54 private final Lock statusLock = new ReentrantLock(); 57 private final Lock statusLock = new ReentrantLock();
55 private volatile Status populationStatus; 58 private volatile Status populationStatus;
59 + private static final int MAX_RETRY_ATTEMPTS = 5;
60 + private ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
56 61
57 /** 62 /**
58 * Represents the default routing population status. 63 * Represents the default routing population status.
...@@ -515,9 +520,17 @@ public class DefaultRoutingHandler { ...@@ -515,9 +520,17 @@ public class DefaultRoutingHandler {
515 * @param deviceId Switch ID to set the rules 520 * @param deviceId Switch ID to set the rules
516 */ 521 */
517 public void populatePortAddressingRules(DeviceId deviceId) { 522 public void populatePortAddressingRules(DeviceId deviceId) {
518 - rulePopulator.populateRouterMacVlanFilters(deviceId);
519 rulePopulator.populateXConnectVlanFilters(deviceId); 523 rulePopulator.populateXConnectVlanFilters(deviceId);
520 rulePopulator.populateRouterIpPunts(deviceId); 524 rulePopulator.populateRouterIpPunts(deviceId);
525 +
526 + // Although device is added, sometimes device store does not have the
527 + // ports for this device yet. It results in missing filtering rules in the
528 + // switch. We will attempt it a few times. If it still does not work,
529 + // user can manually repopulate using CLI command sr-reroute-network
530 + boolean success = rulePopulator.populateRouterMacVlanFilters(deviceId);
531 + if (!success) {
532 + executorService.schedule(new RetryFilters(deviceId), 200, TimeUnit.MILLISECONDS);
533 + }
521 } 534 }
522 535
523 /** 536 /**
...@@ -568,4 +581,25 @@ public class DefaultRoutingHandler { ...@@ -568,4 +581,25 @@ public class DefaultRoutingHandler {
568 updatedEcmpSpgMap.remove(deviceId); 581 updatedEcmpSpgMap.remove(deviceId);
569 } 582 }
570 } 583 }
584 +
585 + private class RetryFilters implements Runnable {
586 + int attempts = MAX_RETRY_ATTEMPTS;
587 + DeviceId devId;
588 +
589 + public RetryFilters(DeviceId deviceId) {
590 + devId = deviceId;
591 + }
592 +
593 + @Override
594 + public void run() {
595 + boolean success = rulePopulator.populateRouterMacVlanFilters(devId);
596 + if (!success && --attempts > 0) {
597 + executorService.schedule(this, 200, TimeUnit.MILLISECONDS);
598 + } else if (attempts == 0) {
599 + log.error("Unable to populate MacVlan filters in dev:{}", devId);
600 + }
601 + }
602 +
603 + }
604 +
571 } 605 }
......
...@@ -62,18 +62,28 @@ public class HostHandler { ...@@ -62,18 +62,28 @@ public class HostHandler {
62 flowObjectiveService = srManager.flowObjectiveService; 62 flowObjectiveService = srManager.flowObjectiveService;
63 } 63 }
64 64
65 - protected void readInitialHosts() { 65 + protected void readInitialHosts(DeviceId devId) {
66 hostService.getHosts().forEach(host -> { 66 hostService.getHosts().forEach(host -> {
67 + DeviceId deviceId = host.location().deviceId();
68 + if (!deviceId.equals(devId)) {
69 + // not an attached host to this device
70 + return;
71 + }
67 MacAddress mac = host.mac(); 72 MacAddress mac = host.mac();
68 VlanId vlanId = host.vlan(); 73 VlanId vlanId = host.vlan();
69 - DeviceId deviceId = host.location().deviceId();
70 PortNumber port = host.location().port(); 74 PortNumber port = host.location().port();
71 Set<IpAddress> ips = host.ipAddresses(); 75 Set<IpAddress> ips = host.ipAddresses();
72 - log.debug("Host {}/{} is added at {}:{}", mac, vlanId, deviceId, port); 76 + log.debug("Attached Host {}/{} is added at {}:{}", mac, vlanId,
77 + deviceId, port);
73 78
74 // Populate bridging table entry 79 // Populate bridging table entry
75 ForwardingObjective.Builder fob = 80 ForwardingObjective.Builder fob =
76 getForwardingObjectiveBuilder(deviceId, mac, vlanId, port); 81 getForwardingObjectiveBuilder(deviceId, mac, vlanId, port);
82 + if (fob == null) {
83 + log.warn("Aborting host bridging & routing table entries due "
84 + + "to error for dev:{} host:{}", deviceId, host);
85 + return;
86 + }
77 ObjectiveContext context = new DefaultObjectiveContext( 87 ObjectiveContext context = new DefaultObjectiveContext(
78 (objective) -> log.debug("Host rule for {} populated", host), 88 (objective) -> log.debug("Host rule for {} populated", host),
79 (objective, error) -> 89 (objective, error) ->
...@@ -127,6 +137,10 @@ public class HostHandler { ...@@ -127,6 +137,10 @@ public class HostHandler {
127 int portNextObjId = srManager.getPortNextObjectiveId(deviceId, outport, 137 int portNextObjId = srManager.getPortNextObjectiveId(deviceId, outport,
128 tbuilder.build(), 138 tbuilder.build(),
129 meta); 139 meta);
140 + if (portNextObjId == -1) {
141 + // warning log will come from getPortNextObjective method
142 + return null;
143 + }
130 144
131 return DefaultForwardingObjective.builder() 145 return DefaultForwardingObjective.builder()
132 .withFlag(ForwardingObjective.Flag.SPECIFIC) 146 .withFlag(ForwardingObjective.Flag.SPECIFIC)
......
...@@ -114,6 +114,11 @@ public class RoutingRulePopulator { ...@@ -114,6 +114,11 @@ public class RoutingRulePopulator {
114 log.warn(e.getMessage() + " Aborting populateIpRuleForHost."); 114 log.warn(e.getMessage() + " Aborting populateIpRuleForHost.");
115 return; 115 return;
116 } 116 }
117 + if (fwdBuilder == null) {
118 + log.warn("Aborting host routing table entries due "
119 + + "to error for dev:{} host:{}", deviceId, hostIp);
120 + return;
121 + }
117 ObjectiveContext context = new DefaultObjectiveContext( 122 ObjectiveContext context = new DefaultObjectiveContext(
118 (objective) -> log.debug("IP rule for host {} populated", hostIp), 123 (objective) -> log.debug("IP rule for host {} populated", hostIp),
119 (objective, error) -> 124 (objective, error) ->
...@@ -191,7 +196,10 @@ public class RoutingRulePopulator { ...@@ -191,7 +196,10 @@ public class RoutingRulePopulator {
191 .matchVlanId(outvlan).build(); 196 .matchVlanId(outvlan).build();
192 int portNextObjId = srManager.getPortNextObjectiveId(deviceId, outPort, 197 int portNextObjId = srManager.getPortNextObjectiveId(deviceId, outPort,
193 treatment, meta); 198 treatment, meta);
194 - 199 + if (portNextObjId == -1) {
200 + // warning log will come from getPortNextObjective method
201 + return null;
202 + }
195 return DefaultForwardingObjective.builder() 203 return DefaultForwardingObjective.builder()
196 .withSelector(selector) 204 .withSelector(selector)
197 .nextStep(portNextObjId) 205 .nextStep(portNextObjId)
...@@ -464,7 +472,7 @@ public class RoutingRulePopulator { ...@@ -464,7 +472,7 @@ public class RoutingRulePopulator {
464 * 472 *
465 * @param deviceId the switch dpid for the router 473 * @param deviceId the switch dpid for the router
466 */ 474 */
467 - public void populateRouterMacVlanFilters(DeviceId deviceId) { 475 + public boolean populateRouterMacVlanFilters(DeviceId deviceId) {
468 log.debug("Installing per-port filtering objective for untagged " 476 log.debug("Installing per-port filtering objective for untagged "
469 + "packets in device {}", deviceId); 477 + "packets in device {}", deviceId);
470 478
...@@ -473,10 +481,17 @@ public class RoutingRulePopulator { ...@@ -473,10 +481,17 @@ public class RoutingRulePopulator {
473 deviceMac = config.getDeviceMac(deviceId); 481 deviceMac = config.getDeviceMac(deviceId);
474 } catch (DeviceConfigNotFoundException e) { 482 } catch (DeviceConfigNotFoundException e) {
475 log.warn(e.getMessage() + " Aborting populateRouterMacVlanFilters."); 483 log.warn(e.getMessage() + " Aborting populateRouterMacVlanFilters.");
476 - return; 484 + return false;
477 } 485 }
478 486
479 - for (Port port : srManager.deviceService.getPorts(deviceId)) { 487 + List<Port> devPorts = srManager.deviceService.getPorts(deviceId);
488 + if (devPorts != null && devPorts.size() == 0) {
489 + log.warn("Device {} ports not available. Unable to add MacVlan filters",
490 + deviceId);
491 + return false;
492 + }
493 +
494 + for (Port port : devPorts) {
480 ConnectPoint connectPoint = new ConnectPoint(deviceId, port.number()); 495 ConnectPoint connectPoint = new ConnectPoint(deviceId, port.number());
481 // TODO: Handles dynamic port events when we are ready for dynamic config 496 // TODO: Handles dynamic port events when we are ready for dynamic config
482 if (!srManager.deviceConfiguration.suppressSubnet().contains(connectPoint) && 497 if (!srManager.deviceConfiguration.suppressSubnet().contains(connectPoint) &&
...@@ -498,6 +513,7 @@ public class RoutingRulePopulator { ...@@ -498,6 +513,7 @@ public class RoutingRulePopulator {
498 fob.withMeta(tt); 513 fob.withMeta(tt);
499 } 514 }
500 fob.permit().fromApp(srManager.appId); 515 fob.permit().fromApp(srManager.appId);
516 + log.debug("Sending filtering objective for dev/port:{}/{}", deviceId, port);
501 ObjectiveContext context = new DefaultObjectiveContext( 517 ObjectiveContext context = new DefaultObjectiveContext(
502 (objective) -> log.debug("Filter for {} populated", connectPoint), 518 (objective) -> log.debug("Filter for {} populated", connectPoint),
503 (objective, error) -> 519 (objective, error) ->
...@@ -505,6 +521,7 @@ public class RoutingRulePopulator { ...@@ -505,6 +521,7 @@ public class RoutingRulePopulator {
505 srManager.flowObjectiveService.filter(deviceId, fob.add(context)); 521 srManager.flowObjectiveService.filter(deviceId, fob.add(context));
506 } 522 }
507 } 523 }
524 + return true;
508 } 525 }
509 526
510 /** 527 /**
......
...@@ -434,6 +434,15 @@ public class SegmentRoutingManager implements SegmentRoutingService { ...@@ -434,6 +434,15 @@ public class SegmentRoutingManager implements SegmentRoutingService {
434 return policyHandler.getPolicies(); 434 return policyHandler.getPolicies();
435 } 435 }
436 436
437 + @Override
438 + public void rerouteNetwork() {
439 + cfgListener.configureNetwork();
440 + for (Device device : deviceService.getDevices()) {
441 + defaultRoutingHandler.populatePortAddressingRules(device.id());
442 + }
443 + defaultRoutingHandler.startPopulationProcess();
444 + }
445 +
437 /** 446 /**
438 * Returns the tunnel object with the tunnel ID. 447 * Returns the tunnel object with the tunnel ID.
439 * 448 *
...@@ -567,7 +576,7 @@ public class SegmentRoutingManager implements SegmentRoutingService { ...@@ -567,7 +576,7 @@ public class SegmentRoutingManager implements SegmentRoutingService {
567 * @param portNum port number on device for which NextObjective is queried 576 * @param portNum port number on device for which NextObjective is queried
568 * @param treatment the actions to apply on the packets (should include outport) 577 * @param treatment the actions to apply on the packets (should include outport)
569 * @param meta metadata passed into the creation of a Next Objective if necessary 578 * @param meta metadata passed into the creation of a Next Objective if necessary
570 - * @return next objective ID or -1 if it was not found 579 + * @return next objective ID or -1 if an error occurred during retrieval or creation
571 */ 580 */
572 public int getPortNextObjectiveId(DeviceId deviceId, PortNumber portNum, 581 public int getPortNextObjectiveId(DeviceId deviceId, PortNumber portNum,
573 TrafficTreatment treatment, 582 TrafficTreatment treatment,
...@@ -801,9 +810,9 @@ public class SegmentRoutingManager implements SegmentRoutingService { ...@@ -801,9 +810,9 @@ public class SegmentRoutingManager implements SegmentRoutingService {
801 // port addressing rules to the driver as well irrespective of whether 810 // port addressing rules to the driver as well irrespective of whether
802 // this instance is the master or not. 811 // this instance is the master or not.
803 defaultRoutingHandler.populatePortAddressingRules(device.id()); 812 defaultRoutingHandler.populatePortAddressingRules(device.id());
804 - hostHandler.readInitialHosts();
805 } 813 }
806 if (mastershipService.isLocalMaster(device.id())) { 814 if (mastershipService.isLocalMaster(device.id())) {
815 + hostHandler.readInitialHosts(device.id());
807 DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id()); 816 DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id());
808 groupHandler.createGroupsFromSubnetConfig(); 817 groupHandler.createGroupsFromSubnetConfig();
809 routingRulePopulator.populateSubnetBroadcastRule(device.id()); 818 routingRulePopulator.populateSubnetBroadcastRule(device.id());
...@@ -897,6 +906,7 @@ public class SegmentRoutingManager implements SegmentRoutingService { ...@@ -897,6 +906,7 @@ public class SegmentRoutingManager implements SegmentRoutingService {
897 // for any switch (even if this instance is a SLAVE or not even connected 906 // for any switch (even if this instance is a SLAVE or not even connected
898 // to the switch). To handle this, a default-group-handler instance is necessary 907 // to the switch). To handle this, a default-group-handler instance is necessary
899 // per switch. 908 // per switch.
909 + log.debug("Current groupHandlerMap devs: {}", groupHandlerMap.keySet());
900 if (groupHandlerMap.get(device.id()) == null) { 910 if (groupHandlerMap.get(device.id()) == null) {
901 DefaultGroupHandler groupHandler; 911 DefaultGroupHandler groupHandler;
902 try { 912 try {
...@@ -911,6 +921,8 @@ public class SegmentRoutingManager implements SegmentRoutingService { ...@@ -911,6 +921,8 @@ public class SegmentRoutingManager implements SegmentRoutingService {
911 log.warn(e.getMessage() + " Aborting configureNetwork."); 921 log.warn(e.getMessage() + " Aborting configureNetwork.");
912 return; 922 return;
913 } 923 }
924 + log.debug("updating groupHandlerMap with new config for "
925 + + "device: {}", device.id());
914 groupHandlerMap.put(device.id(), groupHandler); 926 groupHandlerMap.put(device.id(), groupHandler);
915 927
916 // Also, in some cases, drivers may need extra 928 // Also, in some cases, drivers may need extra
...@@ -918,9 +930,9 @@ public class SegmentRoutingManager implements SegmentRoutingService { ...@@ -918,9 +930,9 @@ public class SegmentRoutingManager implements SegmentRoutingService {
918 // port addressing rules to the driver as well, irrespective of whether 930 // port addressing rules to the driver as well, irrespective of whether
919 // this instance is the master or not. 931 // this instance is the master or not.
920 defaultRoutingHandler.populatePortAddressingRules(device.id()); 932 defaultRoutingHandler.populatePortAddressingRules(device.id());
921 - hostHandler.readInitialHosts();
922 } 933 }
923 if (mastershipService.isLocalMaster(device.id())) { 934 if (mastershipService.isLocalMaster(device.id())) {
935 + hostHandler.readInitialHosts(device.id());
924 DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id()); 936 DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id());
925 groupHandler.createGroupsFromSubnetConfig(); 937 groupHandler.createGroupsFromSubnetConfig();
926 routingRulePopulator.populateSubnetBroadcastRule(device.id()); 938 routingRulePopulator.populateSubnetBroadcastRule(device.id());
......
...@@ -103,4 +103,10 @@ public interface SegmentRoutingService { ...@@ -103,4 +103,10 @@ public interface SegmentRoutingService {
103 * SUCCESS if it is removed successfully 103 * SUCCESS if it is removed successfully
104 */ 104 */
105 PolicyHandler.Result removePolicy(Policy policy); 105 PolicyHandler.Result removePolicy(Policy policy);
106 +
107 + /**
108 + * Use current state of the network to repopulate forwarding rules.
109 + *
110 + */
111 + void rerouteNetwork();
106 } 112 }
......
...@@ -26,7 +26,7 @@ import org.onosproject.segmentrouting.TunnelPolicy; ...@@ -26,7 +26,7 @@ import org.onosproject.segmentrouting.TunnelPolicy;
26 /** 26 /**
27 * Command to add a new policy. 27 * Command to add a new policy.
28 */ 28 */
29 -@Command(scope = "onos", name = "srpolicy-add", 29 +@Command(scope = "onos", name = "sr-policy-add",
30 description = "Create a new policy") 30 description = "Create a new policy")
31 public class PolicyAddCommand extends AbstractShellCommand { 31 public class PolicyAddCommand extends AbstractShellCommand {
32 32
......
...@@ -24,7 +24,7 @@ import org.onosproject.segmentrouting.TunnelPolicy; ...@@ -24,7 +24,7 @@ import org.onosproject.segmentrouting.TunnelPolicy;
24 /** 24 /**
25 * Command to show the list of policies. 25 * Command to show the list of policies.
26 */ 26 */
27 -@Command(scope = "onos", name = "srpolicy-list", 27 +@Command(scope = "onos", name = "sr-policy-list",
28 description = "Lists all policies") 28 description = "Lists all policies")
29 public class PolicyListCommand extends AbstractShellCommand { 29 public class PolicyListCommand extends AbstractShellCommand {
30 30
......
...@@ -26,7 +26,7 @@ import org.onosproject.segmentrouting.TunnelPolicy; ...@@ -26,7 +26,7 @@ import org.onosproject.segmentrouting.TunnelPolicy;
26 /** 26 /**
27 * Command to remove a policy. 27 * Command to remove a policy.
28 */ 28 */
29 -@Command(scope = "onos", name = "srpolicy-remove", 29 +@Command(scope = "onos", name = "sr-policy-remove",
30 description = "Remove a policy") 30 description = "Remove a policy")
31 public class PolicyRemoveCommand extends AbstractShellCommand { 31 public class PolicyRemoveCommand extends AbstractShellCommand {
32 32
......
1 +package org.onosproject.segmentrouting.cli;
2 +
3 +
4 +import org.apache.karaf.shell.commands.Command;
5 +import org.onosproject.cli.AbstractShellCommand;
6 +import org.onosproject.segmentrouting.SegmentRoutingService;
7 +
8 +/**
9 + * Command to manually trigger routing and rule-population in the network.
10 + *
11 + */
12 +@Command(scope = "onos", name = "sr-reroute-network",
13 + description = "Repopulate routing rules given current network state")
14 +public class RerouteNetworkCommand extends AbstractShellCommand {
15 +
16 + @Override
17 + protected void execute() {
18 + SegmentRoutingService srService =
19 + AbstractShellCommand.get(SegmentRoutingService.class);
20 + srService.rerouteNetwork();
21 + }
22 +
23 +}
...@@ -31,7 +31,7 @@ import java.util.StringTokenizer; ...@@ -31,7 +31,7 @@ import java.util.StringTokenizer;
31 /** 31 /**
32 * Command to add a new tunnel. 32 * Command to add a new tunnel.
33 */ 33 */
34 -@Command(scope = "onos", name = "srtunnel-add", 34 +@Command(scope = "onos", name = "sr-tunnel-add",
35 description = "Create a new tunnel") 35 description = "Create a new tunnel")
36 public class TunnelAddCommand extends AbstractShellCommand { 36 public class TunnelAddCommand extends AbstractShellCommand {
37 37
......
...@@ -23,7 +23,7 @@ import org.onosproject.segmentrouting.Tunnel; ...@@ -23,7 +23,7 @@ import org.onosproject.segmentrouting.Tunnel;
23 /** 23 /**
24 * Command to show the list of tunnels. 24 * Command to show the list of tunnels.
25 */ 25 */
26 -@Command(scope = "onos", name = "srtunnel-list", 26 +@Command(scope = "onos", name = "sr-tunnel-list",
27 description = "Lists all tunnels") 27 description = "Lists all tunnels")
28 public class TunnelListCommand extends AbstractShellCommand { 28 public class TunnelListCommand extends AbstractShellCommand {
29 29
......
...@@ -28,7 +28,7 @@ import org.onosproject.segmentrouting.TunnelHandler; ...@@ -28,7 +28,7 @@ import org.onosproject.segmentrouting.TunnelHandler;
28 /** 28 /**
29 * Command to remove a tunnel. 29 * Command to remove a tunnel.
30 */ 30 */
31 -@Command(scope = "onos", name = "srtunnel-remove", 31 +@Command(scope = "onos", name = "sr-tunnel-remove",
32 description = "Remove a tunnel") 32 description = "Remove a tunnel")
33 public class TunnelRemoveCommand extends AbstractShellCommand { 33 public class TunnelRemoveCommand extends AbstractShellCommand {
34 34
......
...@@ -101,8 +101,8 @@ public class DeviceConfiguration implements DeviceProperties { ...@@ -101,8 +101,8 @@ public class DeviceConfiguration implements DeviceProperties {
101 info.mac = config.routerMac(); 101 info.mac = config.routerMac();
102 info.isEdge = config.isEdgeRouter(); 102 info.isEdge = config.isEdgeRouter();
103 info.adjacencySids = config.adjacencySids(); 103 info.adjacencySids = config.adjacencySids();
104 -
105 deviceConfigMap.put(info.deviceId, info); 104 deviceConfigMap.put(info.deviceId, info);
105 + log.info("Read device config for device: {}", info.deviceId);
106 allSegmentIds.add(info.nodeSid); 106 allSegmentIds.add(info.nodeSid);
107 }); 107 });
108 108
......
...@@ -197,6 +197,10 @@ public class DefaultGroupHandler { ...@@ -197,6 +197,10 @@ public class DefaultGroupHandler {
197 197
198 log.info("* LinkUP: Device {} linkUp at local port {} to neighbor {}", deviceId, 198 log.info("* LinkUP: Device {} linkUp at local port {} to neighbor {}", deviceId,
199 newLink.src().port(), newLink.dst().deviceId()); 199 newLink.src().port(), newLink.dst().deviceId());
200 + // ensure local state is updated even if linkup is aborted later on
201 + addNeighborAtPort(newLink.dst().deviceId(),
202 + newLink.src().port());
203 +
200 MacAddress dstMac; 204 MacAddress dstMac;
201 try { 205 try {
202 dstMac = deviceConfig.getDeviceMac(newLink.dst().deviceId()); 206 dstMac = deviceConfig.getDeviceMac(newLink.dst().deviceId());
...@@ -205,8 +209,6 @@ public class DefaultGroupHandler { ...@@ -205,8 +209,6 @@ public class DefaultGroupHandler {
205 return; 209 return;
206 } 210 }
207 211
208 - addNeighborAtPort(newLink.dst().deviceId(),
209 - newLink.src().port());
210 /*if (devicePortMap.get(newLink.dst().deviceId()) == null) { 212 /*if (devicePortMap.get(newLink.dst().deviceId()) == null) {
211 // New Neighbor 213 // New Neighbor
212 newNeighbor(newLink); 214 newNeighbor(newLink);
......
...@@ -34,6 +34,9 @@ ...@@ -34,6 +34,9 @@
34 <command> 34 <command>
35 <action class="org.onosproject.segmentrouting.cli.TunnelRemoveCommand"/> 35 <action class="org.onosproject.segmentrouting.cli.TunnelRemoveCommand"/>
36 </command> 36 </command>
37 + <command>
38 + <action class="org.onosproject.segmentrouting.cli.RerouteNetworkCommand"/>
39 + </command>
37 </command-bundle> 40 </command-bundle>
38 </blueprint> 41 </blueprint>
39 42
......
...@@ -36,6 +36,10 @@ import org.onosproject.net.device.PortStatistics; ...@@ -36,6 +36,10 @@ import org.onosproject.net.device.PortStatistics;
36 description = "Lists statistics of all ports in the system") 36 description = "Lists statistics of all ports in the system")
37 public class DevicePortStatsCommand extends DevicesListCommand { 37 public class DevicePortStatsCommand extends DevicesListCommand {
38 38
39 + @Option(name = "-nz", aliases = "--nonzero", description = "Show only non-zero portstats",
40 + required = false, multiValued = false)
41 + private boolean nonzero = false;
42 +
39 @Option(name = "-d", aliases = "--delta", description = "Show Delta Port Statistics," 43 @Option(name = "-d", aliases = "--delta", description = "Show Delta Port Statistics,"
40 + "only for the last polling interval", 44 + "only for the last polling interval",
41 required = false, multiValued = false) 45 required = false, multiValued = false)
...@@ -100,6 +104,9 @@ public class DevicePortStatsCommand extends DevicesListCommand { ...@@ -100,6 +104,9 @@ public class DevicePortStatsCommand extends DevicesListCommand {
100 if (portNumber != null && stat.port() != portNumber) { 104 if (portNumber != null && stat.port() != portNumber) {
101 continue; 105 continue;
102 } 106 }
107 + if (nonzero && stat.isZero()) {
108 + continue;
109 + }
103 print(FORMAT, stat.port(), stat.packetsReceived(), stat.packetsSent(), stat.bytesReceived(), 110 print(FORMAT, stat.port(), stat.packetsReceived(), stat.packetsSent(), stat.bytesReceived(),
104 stat.bytesSent(), stat.packetsRxDropped(), stat.packetsTxDropped(), stat.durationSec()); 111 stat.bytesSent(), stat.packetsRxDropped(), stat.packetsTxDropped(), stat.durationSec());
105 } 112 }
...@@ -118,6 +125,9 @@ public class DevicePortStatsCommand extends DevicesListCommand { ...@@ -118,6 +125,9 @@ public class DevicePortStatsCommand extends DevicesListCommand {
118 if (portNumber != null && stat.port() != portNumber) { 125 if (portNumber != null && stat.port() != portNumber) {
119 continue; 126 continue;
120 } 127 }
128 + if (nonzero && stat.isZero()) {
129 + continue;
130 + }
121 float duration = ((float) stat.durationSec()) + 131 float duration = ((float) stat.durationSec()) +
122 (((float) stat.durationNano()) / TimeUnit.SECONDS.toNanos(1)); 132 (((float) stat.durationNano()) / TimeUnit.SECONDS.toNanos(1));
123 float rateRx = stat.bytesReceived() * 8 / duration; 133 float rateRx = stat.bytesReceived() * 8 / duration;
...@@ -154,6 +164,9 @@ public class DevicePortStatsCommand extends DevicesListCommand { ...@@ -154,6 +164,9 @@ public class DevicePortStatsCommand extends DevicesListCommand {
154 if (portNumber != null && stat.port() != portNumber) { 164 if (portNumber != null && stat.port() != portNumber) {
155 continue; 165 continue;
156 } 166 }
167 + if (nonzero && stat.isZero()) {
168 + continue;
169 + }
157 float duration = ((float) stat.durationSec()) + 170 float duration = ((float) stat.durationSec()) +
158 (((float) stat.durationNano()) / TimeUnit.SECONDS.toNanos(1)); 171 (((float) stat.durationNano()) / TimeUnit.SECONDS.toNanos(1));
159 float rateRx = stat.bytesReceived() * 8 / duration; 172 float rateRx = stat.bytesReceived() * 8 / duration;
......
...@@ -29,7 +29,7 @@ public class GroupStatusCompleter extends AbstractChoicesCompleter { ...@@ -29,7 +29,7 @@ public class GroupStatusCompleter extends AbstractChoicesCompleter {
29 protected List<String> choices() { 29 protected List<String> choices() {
30 List<String> strings = Lists.newArrayList(); 30 List<String> strings = Lists.newArrayList();
31 for (Group.GroupState groupState : Group.GroupState.values()) { 31 for (Group.GroupState groupState : Group.GroupState.values()) {
32 - strings.add(groupState.toString()); 32 + strings.add(groupState.toString().toLowerCase());
33 } 33 }
34 strings.add(GroupsListCommand.ANY); 34 strings.add(GroupsListCommand.ANY);
35 return strings; 35 return strings;
......
...@@ -142,6 +142,16 @@ public final class DefaultPortStatistics implements PortStatistics { ...@@ -142,6 +142,16 @@ public final class DefaultPortStatistics implements PortStatistics {
142 } 142 }
143 143
144 @Override 144 @Override
145 + public boolean isZero() {
146 + return bytesReceived() == 0 &&
147 + bytesSent() == 0 &&
148 + packetsReceived() == 0 &&
149 + packetsRxDropped() == 0 &&
150 + packetsSent() == 0 &&
151 + packetsTxDropped() == 0;
152 + }
153 +
154 + @Override
145 public String toString() { 155 public String toString() {
146 StringBuilder sb = new StringBuilder("device: " + deviceId + ", "); 156 StringBuilder sb = new StringBuilder("device: " + deviceId + ", ");
147 157
...@@ -343,4 +353,5 @@ public final class DefaultPortStatistics implements PortStatistics { ...@@ -343,4 +353,5 @@ public final class DefaultPortStatistics implements PortStatistics {
343 } 353 }
344 354
345 } 355 }
356 +
346 } 357 }
......
...@@ -97,4 +97,11 @@ public interface PortStatistics { ...@@ -97,4 +97,11 @@ public interface PortStatistics {
97 */ 97 */
98 long durationNano(); 98 long durationNano();
99 99
100 + /**
101 + * Returns true if all the port stats are zero, excluding TxErrors and RxErrors.
102 + *
103 + * @return boolean true if all port stats are zero
104 + */
105 + boolean isZero();
106 +
100 } 107 }
......
...@@ -292,9 +292,11 @@ public class Ofdpa2Pipeline extends AbstractHandlerBehaviour implements Pipeline ...@@ -292,9 +292,11 @@ public class Ofdpa2Pipeline extends AbstractHandlerBehaviour implements Pipeline
292 } else { 292 } else {
293 log.warn("No key defined in filtering objective from app: {}. Not" 293 log.warn("No key defined in filtering objective from app: {}. Not"
294 + "processing filtering objective", applicationId); 294 + "processing filtering objective", applicationId);
295 - fail(filt, ObjectiveError.UNKNOWN); 295 + fail(filt, ObjectiveError.BADPARAMS);
296 return; 296 return;
297 } 297 }
298 + log.debug("Received filtering objective for dev/port: {}/{}", deviceId,
299 + portCriterion.port());
298 // convert filtering conditions for switch-intfs into flowrules 300 // convert filtering conditions for switch-intfs into flowrules
299 FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); 301 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
300 for (Criterion criterion : filt.conditions()) { 302 for (Criterion criterion : filt.conditions()) {
...@@ -333,7 +335,9 @@ public class Ofdpa2Pipeline extends AbstractHandlerBehaviour implements Pipeline ...@@ -333,7 +335,9 @@ public class Ofdpa2Pipeline extends AbstractHandlerBehaviour implements Pipeline
333 } 335 }
334 336
335 if (ethCriterion == null || ethCriterion.mac().equals(MacAddress.NONE)) { 337 if (ethCriterion == null || ethCriterion.mac().equals(MacAddress.NONE)) {
336 - log.debug("filtering objective missing dstMac, cannot program TMAC table"); 338 + log.warn("filtering objective missing dstMac, cannot program TMAC table");
339 + fail(filt, ObjectiveError.BADPARAMS);
340 + return;
337 } else { 341 } else {
338 for (FlowRule tmacRule : processEthDstFilter(portCriterion, ethCriterion, 342 for (FlowRule tmacRule : processEthDstFilter(portCriterion, ethCriterion,
339 vidCriterion, assignedVlan, 343 vidCriterion, assignedVlan,
...@@ -345,8 +349,10 @@ public class Ofdpa2Pipeline extends AbstractHandlerBehaviour implements Pipeline ...@@ -345,8 +349,10 @@ public class Ofdpa2Pipeline extends AbstractHandlerBehaviour implements Pipeline
345 } 349 }
346 350
347 if (ethCriterion == null || vidCriterion == null) { 351 if (ethCriterion == null || vidCriterion == null) {
348 - log.debug("filtering objective missing dstMac or VLAN, " 352 + log.warn("filtering objective missing dstMac or VLAN, "
349 + "cannot program VLAN Table"); 353 + "cannot program VLAN Table");
354 + fail(filt, ObjectiveError.BADPARAMS);
355 + return;
350 } else { 356 } else {
351 /* 357 /*
352 * NOTE: Separate vlan filtering rules and assignment rules 358 * NOTE: Separate vlan filtering rules and assignment rules
...@@ -1079,17 +1085,26 @@ public class Ofdpa2Pipeline extends AbstractHandlerBehaviour implements Pipeline ...@@ -1079,17 +1085,26 @@ public class Ofdpa2Pipeline extends AbstractHandlerBehaviour implements Pipeline
1079 } 1085 }
1080 1086
1081 protected static VlanId readVlanFromSelector(TrafficSelector selector) { 1087 protected static VlanId readVlanFromSelector(TrafficSelector selector) {
1088 + if (selector == null) {
1089 + return null;
1090 + }
1082 Criterion criterion = selector.getCriterion(Criterion.Type.VLAN_VID); 1091 Criterion criterion = selector.getCriterion(Criterion.Type.VLAN_VID);
1083 return (criterion == null) 1092 return (criterion == null)
1084 ? null : ((VlanIdCriterion) criterion).vlanId(); 1093 ? null : ((VlanIdCriterion) criterion).vlanId();
1085 } 1094 }
1086 1095
1087 protected static IpPrefix readIpDstFromSelector(TrafficSelector selector) { 1096 protected static IpPrefix readIpDstFromSelector(TrafficSelector selector) {
1097 + if (selector == null) {
1098 + return null;
1099 + }
1088 Criterion criterion = selector.getCriterion(Criterion.Type.IPV4_DST); 1100 Criterion criterion = selector.getCriterion(Criterion.Type.IPV4_DST);
1089 return (criterion == null) ? null : ((IPCriterion) criterion).ip(); 1101 return (criterion == null) ? null : ((IPCriterion) criterion).ip();
1090 } 1102 }
1091 1103
1092 private static VlanId readVlanFromTreatment(TrafficTreatment treatment) { 1104 private static VlanId readVlanFromTreatment(TrafficTreatment treatment) {
1105 + if (treatment == null) {
1106 + return null;
1107 + }
1093 for (Instruction i : treatment.allInstructions()) { 1108 for (Instruction i : treatment.allInstructions()) {
1094 if (i instanceof ModVlanIdInstruction) { 1109 if (i instanceof ModVlanIdInstruction) {
1095 return ((ModVlanIdInstruction) i).vlanId(); 1110 return ((ModVlanIdInstruction) i).vlanId();
......