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
diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/Ofdpa2Pipeline.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/Ofdpa2Pipeline.java
index 97751ec..ec61771 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/Ofdpa2Pipeline.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/Ofdpa2Pipeline.java
@@ -292,9 +292,11 @@
         } else {
             log.warn("No key defined in filtering objective from app: {}. Not"
                     + "processing filtering objective", applicationId);
-            fail(filt, ObjectiveError.UNKNOWN);
+            fail(filt, ObjectiveError.BADPARAMS);
             return;
         }
+        log.debug("Received filtering objective for dev/port: {}/{}", deviceId,
+                 portCriterion.port());
         // convert filtering conditions for switch-intfs into flowrules
         FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
         for (Criterion criterion : filt.conditions()) {
@@ -333,7 +335,9 @@
         }
 
         if (ethCriterion == null || ethCriterion.mac().equals(MacAddress.NONE)) {
-            log.debug("filtering objective missing dstMac, cannot program TMAC table");
+            log.warn("filtering objective missing dstMac, cannot program TMAC table");
+            fail(filt, ObjectiveError.BADPARAMS);
+            return;
         } else {
             for (FlowRule tmacRule : processEthDstFilter(portCriterion, ethCriterion,
                                                          vidCriterion, assignedVlan,
@@ -345,8 +349,10 @@
         }
 
         if (ethCriterion == null || vidCriterion == null) {
-            log.debug("filtering objective missing dstMac or VLAN, "
+            log.warn("filtering objective missing dstMac or VLAN, "
                     + "cannot program VLAN Table");
+            fail(filt, ObjectiveError.BADPARAMS);
+            return;
         } else {
             /*
              * NOTE: Separate vlan filtering rules and assignment rules
@@ -1079,17 +1085,26 @@
     }
 
     protected static VlanId readVlanFromSelector(TrafficSelector selector) {
+        if (selector == null) {
+            return null;
+        }
         Criterion criterion = selector.getCriterion(Criterion.Type.VLAN_VID);
         return (criterion == null)
                 ? null : ((VlanIdCriterion) criterion).vlanId();
     }
 
     protected static IpPrefix readIpDstFromSelector(TrafficSelector selector) {
+        if (selector == null) {
+            return null;
+        }
         Criterion criterion = selector.getCriterion(Criterion.Type.IPV4_DST);
         return (criterion == null) ? null : ((IPCriterion) criterion).ip();
     }
 
     private static VlanId readVlanFromTreatment(TrafficTreatment treatment) {
+        if (treatment == null) {
+            return null;
+        }
         for (Instruction i : treatment.allInstructions()) {
             if (i instanceof ModVlanIdInstruction) {
                 return ((ModVlanIdInstruction) i).vlanId();