Merge branch 'master' into dev-karaf-4.2.1

Change-Id: I059c6a95489ff5cdc51dd7e98ba44a8415238bc2
diff --git a/WORKSPACE b/WORKSPACE
index 723f0ac..1e83aaa 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -68,6 +68,10 @@
 
 generate_p4lang()
 
+load("//tools/build/bazel:gnmi_workspace.bzl", "generate_gnmi")
+
+generate_gnmi()
+
 git_repository(
     name = "build_bazel_rules_nodejs",
     remote = "https://github.com/bazelbuild/rules_nodejs.git",
diff --git a/apps/odtn/service/src/test/resources/create-connectivity.json b/apps/odtn/service/src/test/resources/create-connectivity.json
index 35798f4..47fd6dc 100644
--- a/apps/odtn/service/src/test/resources/create-connectivity.json
+++ b/apps/odtn/service/src/test/resources/create-connectivity.json
@@ -26,8 +26,8 @@
                 "protection-role" : "WORK"
             }
         ],
-        "conn-constraint" : {},
-        "topo-constraint" : {},
+        "connectivity-constraint" : {},
+        "topology-constraint" : {},
         "resilience-constraint" : [ ]
     }
 }
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingArpHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingArpHandler.java
index 51990d1..2021aa8 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingArpHandler.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingArpHandler.java
@@ -69,6 +69,7 @@
 import org.openstack4j.model.network.Network;
 import org.openstack4j.model.network.Port;
 import org.openstack4j.model.network.Router;
+import org.openstack4j.model.network.RouterInterface;
 import org.osgi.service.component.ComponentContext;
 import org.osgi.service.component.annotations.Activate;
 import org.osgi.service.component.annotations.Component;
@@ -519,27 +520,33 @@
     }
 
     private void setFakeGatewayArpRuleByRouter(Router router, boolean install) {
-        setFakeGatewayArpRuleByGateway(router.getExternalGatewayInfo(), install);
+        setFakeGatewayArpRuleByGateway(router.getId(), router.getExternalGatewayInfo(), install);
     }
 
-    private Set<IP> getExternalGatewaySnatIps(ExternalGateway extGw) {
-        return osNetworkAdminService.ports().stream()
-                .filter(port ->
-                        Objects.equals(port.getNetworkId(), extGw.getNetworkId()))
-                .filter(port ->
-                        Objects.equals(port.getDeviceOwner(), DEVICE_OWNER_ROUTER_GW))
-                .flatMap(port -> port.getFixedIps().stream())
+    private Set<IP> getExternalGatewaySnatIps(String routerId, ExternalGateway extGw) {
+        if (routerId == null) {
+            return ImmutableSet.of();
+        }
+
+        Set<String> portIds = osRouterAdminService.routerInterfaces(routerId).stream()
+                .map(RouterInterface::getPortId)
+                .collect(Collectors.toSet());
+
+        return portIds.stream()
+                .map(pid -> osNetworkAdminService.port(pid))
+                .filter(p -> Objects.equals(p.getDeviceOwner(), DEVICE_OWNER_ROUTER_GW))
+                .flatMap(p -> p.getFixedIps().stream())
                 .collect(Collectors.toSet());
     }
 
-    private void setFakeGatewayArpRuleByGateway(ExternalGateway extGw, boolean install) {
+    private void setFakeGatewayArpRuleByGateway(String routerId, ExternalGateway extGw, boolean install) {
         if (ARP_BROADCAST_MODE.equals(getArpMode())) {
 
             if (extGw == null) {
                 return;
             }
 
-            setFakeGatewayArpRuleByIps(getExternalGatewaySnatIps(extGw), install);
+            setFakeGatewayArpRuleByIps(getExternalGatewaySnatIps(routerId, extGw), install);
         }
     }
 
@@ -653,13 +660,15 @@
                 case OPENSTACK_ROUTER_GATEWAY_ADDED:
                     eventExecutor.execute(() ->
                         // add a gateway manually after adding a router
-                        setFakeGatewayArpRuleByGateway(event.externalGateway(), true)
+                        setFakeGatewayArpRuleByGateway(event.subject().getId(),
+                                                        event.externalGateway(), true)
                     );
                     break;
                 case OPENSTACK_ROUTER_GATEWAY_REMOVED:
                     eventExecutor.execute(() ->
                         // remove a gateway from an existing router
-                        setFakeGatewayArpRuleByGateway(event.externalGateway(), false)
+                        setFakeGatewayArpRuleByGateway(event.subject().getId(),
+                                                        event.externalGateway(), false)
                     );
                     break;
                 case OPENSTACK_FLOATING_IP_ASSOCIATED:
@@ -875,6 +884,11 @@
         }
 
         private void setDefaultArpRule(OpenstackNode osNode, boolean install) {
+
+            if (getArpMode() == null) {
+                return;
+            }
+
             switch (getArpMode()) {
                 case ARP_PROXY_MODE:
                     setDefaultArpRuleForProxyMode(osNode, install);
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingHandler.java
index 1a9de18..edcf6ed 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingHandler.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingHandler.java
@@ -482,15 +482,15 @@
     private void setInternalRoutes(Router osRouter, Subnet updatedSubnet, boolean install) {
         Network updatedNetwork = osNetworkAdminService.network(updatedSubnet.getNetworkId());
         Set<Subnet> routableSubnets = routableSubnets(osRouter, updatedSubnet.getId());
-        String updatedSegmendId = getSegmentId(updatedSubnet);
+        String updatedSegmentId = getSegmentId(updatedSubnet);
 
         // installs rule from/to my subnet intentionally to fix ICMP failure
         // to my subnet gateway if no external gateway added to the router
         osNodeService.completeNodes(COMPUTE).forEach(cNode -> {
             setInternalRouterRules(
                     cNode.intgBridge(),
-                    updatedSegmendId,
-                    updatedSegmendId,
+                    updatedSegmentId,
+                    updatedSegmentId,
                     IpPrefix.valueOf(updatedSubnet.getCidr()),
                     IpPrefix.valueOf(updatedSubnet.getCidr()),
                     updatedNetwork.getNetworkType(),
@@ -500,7 +500,7 @@
             routableSubnets.forEach(subnet -> {
                 setInternalRouterRules(
                         cNode.intgBridge(),
-                        updatedSegmendId,
+                        updatedSegmentId,
                         getSegmentId(subnet),
                         IpPrefix.valueOf(updatedSubnet.getCidr()),
                         IpPrefix.valueOf(subnet.getCidr()),
@@ -510,7 +510,7 @@
                 setInternalRouterRules(
                         cNode.intgBridge(),
                         getSegmentId(subnet),
-                        updatedSegmendId,
+                        updatedSegmentId,
                         IpPrefix.valueOf(subnet.getCidr()),
                         IpPrefix.valueOf(updatedSubnet.getCidr()),
                         updatedNetwork.getNetworkType(),
@@ -854,7 +854,6 @@
                 .matchIPSrc(srcSubnet)
                 .matchEthDst(Constants.DEFAULT_GATEWAY_MAC);
 
-
         switch (networkType) {
             case VXLAN:
                 sBuilder.matchTunnelId(Long.parseLong(segmentId));
@@ -886,7 +885,14 @@
                 GW_COMMON_TABLE,
                 install);
 
+        // TODO: we do not remove the IcmpReplyMatchRules with false installation flag
+        // need to find a better way to remove this rule
+        if (install) {
+            setIcmpReplyRules(deviceId, install);
+        }
+    }
 
+    private void setIcmpReplyRules(DeviceId deviceId, boolean install) {
         // Sends ICMP response to controller for SNATing ingress traffic
         TrafficSelector selector = DefaultTrafficSelector.builder()
                 .matchEthType(Ethernet.TYPE_IPV4)
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingIcmpHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingIcmpHandler.java
index 0fab57f..1cc02b7 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingIcmpHandler.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingIcmpHandler.java
@@ -93,6 +93,9 @@
     private static final String ERR_REQ = "Failed to handle ICMP request: ";
     private static final String ERR_DUPLICATE = " already exists";
 
+    private static final String VXLAN = "VXLAN";
+    private static final String VLAN = "VLAN";
+
     @Reference(cardinality = ReferenceCardinality.MANDATORY)
     protected CoreService coreService;
 
@@ -407,13 +410,26 @@
     }
 
     private void sendReply(Ethernet icmpReply, InstancePort instPort) {
-        TrafficTreatment treatment = DefaultTrafficTreatment.builder()
-                .setOutput(instPort.portNumber())
-                .build();
+        TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
+                .setOutput(instPort.portNumber());
+
+        String netId = instPort.networkId();
+        String segId = osNetworkService.segmentId(netId);
+
+        switch (osNetworkService.networkType(netId)) {
+            case VXLAN:
+                tBuilder.setTunnelId(Long.valueOf(segId));
+                break;
+            case VLAN:
+                tBuilder.setVlanId(VlanId.vlanId(segId));
+                break;
+            default:
+                break;
+        }
 
         OutboundPacket packet = new DefaultOutboundPacket(
                 instPort.deviceId(),
-                treatment,
+                tBuilder.build(),
                 ByteBuffer.wrap(icmpReply.serialize()));
 
         packetService.emit(packet);
@@ -435,7 +451,8 @@
                 return;
             }
 
-            if (!gateways.isEmpty() && !gateways.contains(context.inPacket().receivedFrom().deviceId())) {
+            if (!gateways.isEmpty() &&
+                    !gateways.contains(context.inPacket().receivedFrom().deviceId())) {
                 return;
             }
 
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSecurityGroupHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSecurityGroupHandler.java
index 863e40a..ba9ec96 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSecurityGroupHandler.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSecurityGroupHandler.java
@@ -42,6 +42,7 @@
 import org.onosproject.net.flow.TrafficSelector;
 import org.onosproject.net.flow.TrafficTreatment;
 import org.onosproject.net.flow.criteria.ExtensionSelector;
+import org.onosproject.net.flow.instructions.ExtensionTreatment;
 import org.onosproject.openstacknetworking.api.InstancePort;
 import org.onosproject.openstacknetworking.api.InstancePortAdminService;
 import org.onosproject.openstacknetworking.api.InstancePortEvent;
@@ -54,7 +55,6 @@
 import org.onosproject.openstacknetworking.api.OpenstackSecurityGroupListener;
 import org.onosproject.openstacknetworking.api.OpenstackSecurityGroupService;
 import org.onosproject.openstacknetworking.util.RulePopulatorUtil;
-import org.onosproject.openstacknode.api.OpenstackNode;
 import org.onosproject.openstacknode.api.OpenstackNodeEvent;
 import org.onosproject.openstacknode.api.OpenstackNodeListener;
 import org.onosproject.openstacknode.api.OpenstackNodeService;
@@ -176,13 +176,13 @@
             .build();
 
     private final InstancePortListener instancePortListener =
-                                        new InternalInstancePortListener();
+            new InternalInstancePortListener();
     private final OpenstackNetworkListener osNetworkListener =
-                                        new InternalOpenstackNetworkListener();
+            new InternalOpenstackNetworkListener();
     private final OpenstackNetworkListener osPortListener =
-                                        new InternalOpenstackPortListener();
+            new InternalOpenstackPortListener();
     private final OpenstackSecurityGroupListener securityGroupListener =
-                                        new InternalSecurityGroupListener();
+            new InternalSecurityGroupListener();
     private final OpenstackNodeListener osNodeListener = new InternalNodeListener();
 
     private ConsistentMap<String, Port> removedOsPortStore;
@@ -335,10 +335,10 @@
                         SecurityGroupRule rSgRule =
                                 new NeutronSecurityGroupRule
                                         .SecurityGroupRuleConcreteBuilder()
-                                .from(sgRule)
-                                .direction(sgRule.getDirection().toUpperCase()
-                                            .equals(EGRESS) ? INGRESS : EGRESS)
-                                .build();
+                                        .from(sgRule)
+                                        .direction(sgRule.getDirection().toUpperCase()
+                                                .equals(EGRESS) ? INGRESS : EGRESS)
+                                        .build();
                         populateSecurityGroupRule(rSgRule, instPort, port,
                                 rInstPort.ipAddress().toIpPrefix(), install);
                         populateSecurityGroupRule(rSgRule, rInstPort, port,
@@ -347,7 +347,7 @@
         } else {
             populateSecurityGroupRule(sgRule, instPort, port,
                     sgRule.getRemoteIpPrefix() == null ? IP_PREFIX_ANY :
-                    IpPrefix.valueOf(sgRule.getRemoteIpPrefix()), install);
+                            IpPrefix.valueOf(sgRule.getRemoteIpPrefix()), install);
         }
     }
 
@@ -362,14 +362,25 @@
             return;
         }
 
+        // XXX All egress traffic needs to go through connection tracking module,
+        // which might hurt its performance.
+        ExtensionTreatment ctTreatment =
+                niciraConnTrackTreatmentBuilder(driverService, instPort.deviceId())
+                        .commit(true)
+                        .build();
+
+        TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+                .extension(ctTreatment, instPort.deviceId())
+                .transition(JUMP_TABLE)
+                .build();
+
         selectors.forEach(selector ->
                 osFlowRuleService.setRule(appId,
-                instPort.deviceId(),
-                selector,
-                DefaultTrafficTreatment.builder().transition(JUMP_TABLE).build(),
-                PRIORITY_ACL_RULE,
-                ACL_TABLE,
-                install));
+                        instPort.deviceId(),
+                        selector, treatment,
+                        PRIORITY_ACL_RULE,
+                        ACL_TABLE,
+                        install));
     }
 
     /**
@@ -490,7 +501,7 @@
                 sgRule.getPortRangeMin() < sgRule.getPortRangeMax()) {
             Map<TpPort, TpPort> portRangeMatchMap =
                     buildPortRangeMatches(sgRule.getPortRangeMin(),
-                    sgRule.getPortRangeMax());
+                            sgRule.getPortRangeMax());
             portRangeMatchMap.forEach((key, value) -> {
 
                 if (sgRule.getProtocol().toUpperCase().equals(PROTO_TCP)) {
@@ -527,9 +538,6 @@
                 sgRule.getPortRangeMin() == null ? 0 : sgRule.getPortRangeMin(),
                 sgRule.getPortRangeMax() == null ? 0 : sgRule.getPortRangeMax());
         buildMatchRemoteIp(sBuilder, remoteIp, sgRule.getDirection());
-        if (sgRule.getRemoteGroupId() != null && sgRule.getRemoteGroupId().isEmpty()) {
-            buildMatchRemoteIp(sBuilder, remoteIp, sgRule.getDirection());
-        }
     }
 
     private void buildTunnelId(TrafficSelector.Builder sBuilder, Port port) {
@@ -540,6 +548,8 @@
             sBuilder.matchVlanId(VlanId.vlanId(segId));
         } else if (VXLAN.equals(netType)) {
             sBuilder.matchTunnelId(Long.valueOf(segId));
+        } else {
+            log.warn("Cannot tag the VID due to lack of support of virtual network type {}", netType);
         }
     }
 
@@ -614,33 +624,31 @@
     private void resetSecurityGroupRules() {
 
         if (useSecurityGroup) {
-            osNodeService.completeNodes(OpenstackNode.NodeType.COMPUTE)
-                    .forEach(node -> osFlowRuleService
-                            .setUpTableMissEntry(node.intgBridge(), ACL_TABLE));
+            osNodeService.completeNodes(COMPUTE).forEach(node -> {
+                osFlowRuleService.setUpTableMissEntry(node.intgBridge(), ACL_TABLE);
+                initializeConnTrackTable(node.intgBridge(), true);
+            });
+
             securityGroupService.securityGroups().forEach(securityGroup ->
                     securityGroup.getRules().forEach(this::securityGroupRuleAdded));
-            osNodeService.nodes().stream()
-                    .filter(node -> node.type().equals(OpenstackNode.NodeType.COMPUTE))
-                    .forEach(node -> initializeConnTrackTable(node .intgBridge(), true));
         } else {
-            osNodeService.completeNodes(OpenstackNode.NodeType.COMPUTE)
-                    .forEach(node -> osFlowRuleService
-                            .connectTables(node.intgBridge(), ACL_TABLE, JUMP_TABLE));
+            osNodeService.completeNodes(COMPUTE).forEach(node -> {
+                osFlowRuleService.connectTables(node.intgBridge(), ACL_TABLE, JUMP_TABLE);
+                initializeConnTrackTable(node.intgBridge(), false);
+            });
+
             securityGroupService.securityGroups().forEach(securityGroup ->
                     securityGroup.getRules().forEach(this::securityGroupRuleRemoved));
-            osNodeService.nodes().stream()
-                    .filter(node -> node.type().equals(OpenstackNode.NodeType.COMPUTE))
-                    .forEach(node -> initializeConnTrackTable(node.intgBridge(), false));
         }
 
         log.info("Reset security group info " +
-                    (useSecurityGroup ? " with " : " without") + " Security Group");
+                (useSecurityGroup ? " with " : " without") + " Security Group");
     }
 
     private void securityGroupRuleAdded(SecurityGroupRule sgRule) {
         osNetService.ports().stream()
                 .filter(port -> port.getSecurityGroups()
-                                    .contains(sgRule.getSecurityGroupId()))
+                        .contains(sgRule.getSecurityGroupId()))
                 .forEach(port -> {
                     updateSecurityGroupRule(
                             instancePortService.instancePort(port.getId()),
@@ -655,7 +663,7 @@
 
         Sets.union(osNetService.ports(), removedPorts).stream()
                 .filter(port -> port.getSecurityGroups()
-                                    .contains(sgRule.getSecurityGroupId()))
+                        .contains(sgRule.getSecurityGroupId()))
                 .forEach(port -> {
                     updateSecurityGroupRule(
                             instancePortService.instancePort(port.getId()),
@@ -825,7 +833,7 @@
     }
 
     private class InternalOpenstackNetworkListener
-                                            implements OpenstackNetworkListener {
+            implements OpenstackNetworkListener {
 
         @Override
         public boolean isRelevant(OpenstackNetworkEvent event) {
@@ -881,7 +889,7 @@
     }
 
     private class InternalSecurityGroupListener
-                                    implements OpenstackSecurityGroupListener {
+            implements OpenstackSecurityGroupListener {
 
         @Override
         public boolean isRelevant(OpenstackSecurityGroupEvent event) {
@@ -936,22 +944,9 @@
 
         @Override
         public void event(OpenstackNodeEvent event) {
-            OpenstackNode osNode = event.subject();
-
             switch (event.type()) {
                 case OPENSTACK_NODE_COMPLETE:
-                    eventExecutor.execute(() -> {
-                        try {
-                            if (useSecurityGroup) {
-                                initializeConnTrackTable(osNode.intgBridge(), true);
-                                log.info("SG table initialization : {} is done",
-                                                            osNode.intgBridge());
-                            }
-                        } catch (IllegalArgumentException e) {
-                            log.error("ACL table initialization error : {}",
-                                                            e.getMessage());
-                        }
-                    });
+                    resetSecurityGroupRules();
                     break;
                 case OPENSTACK_NODE_CREATED:
                 case OPENSTACK_NODE_REMOVED:
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingHandler.java
index b348d49..f6977a3 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingHandler.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingHandler.java
@@ -39,7 +39,6 @@
 import org.onosproject.net.flow.DefaultTrafficTreatment;
 import org.onosproject.net.flow.TrafficSelector;
 import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.flow.instructions.ExtensionTreatment;
 import org.onosproject.openstacknetworking.api.InstancePort;
 import org.onosproject.openstacknetworking.api.InstancePortEvent;
 import org.onosproject.openstacknetworking.api.InstancePortListener;
@@ -49,7 +48,6 @@
 import org.onosproject.openstacknetworking.api.OpenstackNetworkListener;
 import org.onosproject.openstacknetworking.api.OpenstackNetworkService;
 import org.onosproject.openstacknetworking.api.OpenstackSecurityGroupService;
-import org.onosproject.openstacknetworking.util.RulePopulatorUtil;
 import org.onosproject.openstacknode.api.OpenstackNode;
 import org.onosproject.openstacknode.api.OpenstackNodeService;
 import org.openstack4j.model.network.Network;
@@ -501,25 +499,21 @@
                 .matchInPort(instPort.portNumber())
                 .build();
 
-        // XXX All egress traffic needs to go through connection tracking module,
-        // which might hurt its performance.
-        ExtensionTreatment ctTreatment =
-                RulePopulatorUtil.niciraConnTrackTreatmentBuilder(driverService, instPort.deviceId())
-                        .commit(true).build();
+        TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
+                .setTunnelId(getVni(instPort));
 
-        TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder()
-                .setTunnelId(getVni(instPort))
-                .transition(ARP_TABLE);
 
-        if (securityGroupService.isSecurityGroupEnabled() && ethType == Ethernet.TYPE_IPV4) {
-            tb.extension(ctTreatment, instPort.deviceId());
+        if (ethType == Ethernet.TYPE_ARP) {
+            tBuilder.transition(ARP_TABLE);
+        } else if (ethType == Ethernet.TYPE_IPV4) {
+            tBuilder.transition(ACL_TABLE);
         }
 
         osFlowRuleService.setRule(
                 appId,
                 instPort.deviceId(),
                 selector,
-                tb.build(),
+                tBuilder.build(),
                 PRIORITY_TUNNEL_TAG_RULE,
                 VTAG_TABLE,
                 install);
diff --git a/apps/route-service/app/src/main/java/org/onosproject/routeservice/cli/RouteRemoveCommand.java b/apps/route-service/app/src/main/java/org/onosproject/routeservice/cli/RouteRemoveCommand.java
index eb6f01c..8fb29ec 100644
--- a/apps/route-service/app/src/main/java/org/onosproject/routeservice/cli/RouteRemoveCommand.java
+++ b/apps/route-service/app/src/main/java/org/onosproject/routeservice/cli/RouteRemoveCommand.java
@@ -43,6 +43,10 @@
             required = true)
     String nextHopString = null;
 
+    @Argument(index = 2, name = "source", description = "Source type of the route",
+            required = false)
+    String source = null;
+
     @Override
     protected void doExecute() {
         RouteAdminService service = AbstractShellCommand.get(RouteAdminService.class);
@@ -50,7 +54,14 @@
         IpPrefix prefix = IpPrefix.valueOf(prefixString);
         IpAddress nextHop = IpAddress.valueOf(nextHopString);
 
-        service.withdraw(Collections.singleton(new Route(Route.Source.STATIC, prefix, nextHop)));
+        // Routes through cli without mentioning source then it is created as STATIC,
+        // otherwise routes are created with corresponding source.
+
+        Route route = source == null ?
+                new Route(Route.Source.STATIC, prefix, nextHop) :
+                new Route(Route.Source.valueOf(source), prefix, nextHop);
+
+        service.withdraw(Collections.singleton(route));
     }
 
 }
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/HostHandler.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/HostHandler.java
index ffc0e4d..ae35f7b 100644
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/HostHandler.java
+++ b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/HostHandler.java
@@ -448,18 +448,37 @@
      * @param pairRemotePort pair remote port
      */
     private void probe(Host host, ConnectPoint location, DeviceId pairDeviceId, PortNumber pairRemotePort) {
+        //Check if the host still exists in the host store
+        if (hostService.getHost(host.id()) == null) {
+            log.debug("Host entry for host {} no more present. Aborting hostprobe discover for this host", host.id());
+            return;
+        }
+
         VlanId vlanToProbe = host.vlan().equals(VlanId.NONE) ?
                 srManager.getInternalVlanId(location) : host.vlan();
-        srManager.interfaceService.getInterfaces().stream()
-                .filter(i -> i.vlanTagged().contains(vlanToProbe) ||
-                        i.vlanUntagged().equals(vlanToProbe) ||
-                        i.vlanNative().equals(vlanToProbe))
-                .filter(i -> i.connectPoint().deviceId().equals(pairDeviceId))
-                .filter(i -> !i.connectPoint().port().equals(pairRemotePort))
-                .forEach(i -> {
-                    log.debug("Probing host {} on pair device {}", host.id(), i.connectPoint());
-                    srManager.probingService.probeHost(host, i.connectPoint(), ProbeMode.DISCOVER);
-                });
+        if (srManager.symmetricProbing) {
+            srManager.interfaceService.getInterfaces().stream()
+                    .filter(i -> i.vlanTagged().contains(vlanToProbe) ||
+                            i.vlanUntagged().equals(vlanToProbe) ||
+                            i.vlanNative().equals(vlanToProbe))
+                    .filter(i -> i.connectPoint().deviceId().equals(pairDeviceId))
+                    .filter(i -> i.connectPoint().port().equals(location.port()))
+                    .forEach(i -> {
+                        log.debug("Probing host {} on pair device {}", host.id(), i.connectPoint());
+                        srManager.probingService.probeHost(host, i.connectPoint(), ProbeMode.DISCOVER);
+                    });
+        } else {
+            srManager.interfaceService.getInterfaces().stream()
+                    .filter(i -> i.vlanTagged().contains(vlanToProbe) ||
+                            i.vlanUntagged().equals(vlanToProbe) ||
+                            i.vlanNative().equals(vlanToProbe))
+                    .filter(i -> i.connectPoint().deviceId().equals(pairDeviceId))
+                    .filter(i -> !i.connectPoint().port().equals(pairRemotePort))
+                    .forEach(i -> {
+                        log.debug("Probing host {} on pair device {}", host.id(), i.connectPoint());
+                        srManager.probingService.probeHost(host, i.connectPoint(), ProbeMode.DISCOVER);
+                    });
+        }
     }
 
     /**
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/OsgiPropertyConstants.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/OsgiPropertyConstants.java
index 399e95b..7b5a6fc 100644
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/OsgiPropertyConstants.java
+++ b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/OsgiPropertyConstants.java
@@ -41,4 +41,7 @@
     public static final String PROP_PW_TRANSPORT_VLAN = "pwTransportVlan";
     public static final int PW_TRANSPORT_VLAN_DEFAULT = 4090;
 
+    static final String PROP_SYMMETRIC_PROBING = "symmetricProbing";
+    static final boolean SYMMETRIC_PROBING_DEFAULT = false;
+
 }
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
index 17e733c..c75de3c 100644
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
+++ b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
@@ -165,10 +165,12 @@
 import static org.onosproject.segmentrouting.OsgiPropertyConstants.PROP_RESPOND_TO_UNKNOWN_HOSTS;
 import static org.onosproject.segmentrouting.OsgiPropertyConstants.PROP_ROUTE_DOUBLE_TAGGED_HOSTS;
 import static org.onosproject.segmentrouting.OsgiPropertyConstants.PROP_SINGLE_HOMED_DOWN;
+import static org.onosproject.segmentrouting.OsgiPropertyConstants.PROP_SYMMETRIC_PROBING;
 import static org.onosproject.segmentrouting.OsgiPropertyConstants.PW_TRANSPORT_VLAN_DEFAULT;
 import static org.onosproject.segmentrouting.OsgiPropertyConstants.RESPOND_TO_UNKNOWN_HOSTS_DEFAULT;
 import static org.onosproject.segmentrouting.OsgiPropertyConstants.ROUTE_DOUBLE_TAGGED_HOSTS_DEFAULT;
 import static org.onosproject.segmentrouting.OsgiPropertyConstants.SINGLE_HOMED_DOWN_DEFAULT;
+import static org.onosproject.segmentrouting.OsgiPropertyConstants.SYMMETRIC_PROBING_DEFAULT;
 
 /**
  * Segment routing manager.
@@ -183,6 +185,7 @@
         PROP_ROUTE_DOUBLE_TAGGED_HOSTS + ":Boolean=" + ROUTE_DOUBLE_TAGGED_HOSTS_DEFAULT,
         PROP_DEFAULT_INTERNAL_VLAN + ":Integer=" + DEFAULT_INTERNAL_VLAN_DEFAULT,
         PROP_PW_TRANSPORT_VLAN + ":Integer=" + PW_TRANSPORT_VLAN_DEFAULT,
+        PROP_SYMMETRIC_PROBING + ":Boolean=" + SYMMETRIC_PROBING_DEFAULT
     }
 )
 public class SegmentRoutingManager implements SegmentRoutingService {
@@ -256,6 +259,9 @@
     /** Enable active probing to discover dual-homed hosts. */
     boolean activeProbing = ACTIVE_PROBING_DEFAULT;
 
+    /** Enable only send probe on the same port number of the pair device. */
+    boolean symmetricProbing = SYMMETRIC_PROBING_DEFAULT;
+
     /** Enable administratively taking down single-homed hosts. */
     boolean singleHomedDown = SINGLE_HOMED_DOWN_DEFAULT;
 
@@ -625,6 +631,14 @@
             log.info("{} active probing", activeProbing ? "Enabling" : "Disabling");
         }
 
+
+        String strSymmetricProbing = Tools.get(properties, PROP_SYMMETRIC_PROBING);
+        boolean expectSymmetricProbing = Boolean.parseBoolean(strSymmetricProbing);
+        if (expectSymmetricProbing != symmetricProbing) {
+            symmetricProbing = expectSymmetricProbing;
+            log.info("{} symmetric probing", symmetricProbing ? "Enabling" : "Disabling");
+        }
+
         String strSingleHomedDown = Tools.get(properties, PROP_SINGLE_HOMED_DOWN);
         boolean expectSingleHomedDown = Boolean.parseBoolean(strSingleHomedDown);
         if (expectSingleHomedDown != singleHomedDown) {
diff --git a/core/api/src/main/java/org/onosproject/net/group/DefaultGroupDescription.java b/core/api/src/main/java/org/onosproject/net/group/DefaultGroupDescription.java
index e047062..4322482 100644
--- a/core/api/src/main/java/org/onosproject/net/group/DefaultGroupDescription.java
+++ b/core/api/src/main/java/org/onosproject/net/group/DefaultGroupDescription.java
@@ -65,7 +65,8 @@
         if (this.type == GroupDescription.Type.INDIRECT) {
             checkArgument(buckets.buckets().size() == 1, "Indirect group " +
                     "should have only one action bucket");
-       }
+        }
+        checkArgument(buckets.buckets().stream().allMatch(b -> b.type() == type), "Inconsistent bucket type");
         this.appCookie = appCookie;
         this.givenGroupId = groupId;
         this.appId = appId;
diff --git a/core/api/src/test/java/org/onosproject/net/group/DefaultGroupDescriptionTest.java b/core/api/src/test/java/org/onosproject/net/group/DefaultGroupDescriptionTest.java
index 0a0a093..3d2d368 100644
--- a/core/api/src/test/java/org/onosproject/net/group/DefaultGroupDescriptionTest.java
+++ b/core/api/src/test/java/org/onosproject/net/group/DefaultGroupDescriptionTest.java
@@ -16,6 +16,8 @@
 package org.onosproject.net.group;
 
 import org.junit.Test;
+import org.onosproject.core.GroupId;
+import org.onosproject.net.PortNumber;
 import org.onosproject.net.flow.DefaultTrafficTreatment;
 import org.onosproject.net.flow.TrafficTreatment;
 
@@ -32,28 +34,31 @@
  * Default group description unit tests.
  */
 public class DefaultGroupDescriptionTest {
-    byte[] keyData = "abcdefg".getBytes();
+    private final byte[] keyData = "abcdefg".getBytes();
     private final GroupKey key = new DefaultGroupKey(keyData);
-    private final TrafficTreatment treatment =
-            DefaultTrafficTreatment.emptyTreatment();
-    private final GroupBucket bucket =
-            DefaultGroupBucket.createSelectGroupBucket(treatment);
-    private final GroupBuckets groupBuckets =
-            new GroupBuckets(ImmutableList.of(bucket));
+    private final GroupId groupId1 = new GroupId(1);
+    private final TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
+
+    private final GroupBucket failoverGroupBucket =
+            DefaultGroupBucket.createFailoverGroupBucket(treatment, PortNumber.IN_PORT, groupId1);
+    private final GroupBuckets failoverGroupBuckets = new GroupBuckets(ImmutableList.of(failoverGroupBucket));
+    private final GroupBucket indirectGroupBucket =
+            DefaultGroupBucket.createIndirectGroupBucket(treatment);
+    private final GroupBuckets indirectGroupBuckets = new GroupBuckets(ImmutableList.of(indirectGroupBucket));
+
     private final DefaultGroupDescription d1 =
             new DefaultGroupDescription(did("2"),
                     GroupDescription.Type.FAILOVER,
-                    groupBuckets);
-    private final DefaultGroupDescription sameAsD1 =
-            new DefaultGroupDescription(d1);
+                    failoverGroupBuckets);
+    private final DefaultGroupDescription sameAsD1 = new DefaultGroupDescription(d1);
     private final DefaultGroupDescription d2 =
             new DefaultGroupDescription(did("2"),
                     GroupDescription.Type.INDIRECT,
-                    groupBuckets);
+                    indirectGroupBuckets);
     private final DefaultGroupDescription d3 =
             new DefaultGroupDescription(did("3"),
                     GroupDescription.Type.FAILOVER,
-                    groupBuckets,
+                    failoverGroupBuckets,
                     key,
                     711,
                     APP_ID);
@@ -86,7 +91,7 @@
     public void testConstruction() {
         assertThat(d3.deviceId(), is(did("3")));
         assertThat(d3.type(), is(GroupDescription.Type.FAILOVER));
-        assertThat(d3.buckets(), is(groupBuckets));
+        assertThat(d3.buckets(), is(failoverGroupBuckets));
         assertThat(d3.appId(), is(APP_ID));
         assertThat(d3.givenGroupId(), is(711));
         assertThat(key.key(), is(keyData));
diff --git a/core/api/src/test/java/org/onosproject/net/group/DefaultGroupTest.java b/core/api/src/test/java/org/onosproject/net/group/DefaultGroupTest.java
index e8fb7b3..c84ac87 100644
--- a/core/api/src/test/java/org/onosproject/net/group/DefaultGroupTest.java
+++ b/core/api/src/test/java/org/onosproject/net/group/DefaultGroupTest.java
@@ -18,6 +18,7 @@
 import org.junit.Test;
 import org.onosproject.core.GroupId;
 import org.onosproject.net.NetTestTools;
+import org.onosproject.net.PortNumber;
 import org.onosproject.net.flow.DefaultTrafficTreatment;
 
 import com.google.common.collect.ImmutableList;
@@ -35,24 +36,20 @@
     private final GroupId id2 = new GroupId(7);
     private final GroupId id3 = new GroupId(1234);
 
-    private final GroupBucket bucket =
-            DefaultGroupBucket.createSelectGroupBucket(
-                    DefaultTrafficTreatment.emptyTreatment());
-    private final GroupBuckets groupBuckets =
-            new GroupBuckets(ImmutableList.of(bucket));
-    private final GroupDescription groupDesc1 =
-            new DefaultGroupDescription(did("1"),
-                    GroupDescription.Type.FAILOVER,
-                    groupBuckets);
-    private final GroupDescription groupDesc2 =
-            new DefaultGroupDescription(did("2"),
-                    GroupDescription.Type.FAILOVER,
-                    groupBuckets);
+    private final GroupBucket failoverBucket = DefaultGroupBucket.createFailoverGroupBucket(
+            DefaultTrafficTreatment.emptyTreatment(), PortNumber.IN_PORT, id1);
+    private final GroupBuckets failoverGroupBuckets = new GroupBuckets(ImmutableList.of(failoverBucket));
 
-     private final GroupDescription groupDesc3 =
-            new DefaultGroupDescription(did("3"),
-                    GroupDescription.Type.INDIRECT,
-                    groupBuckets);
+    private final GroupBucket indirectBucket =
+            DefaultGroupBucket.createIndirectGroupBucket(DefaultTrafficTreatment.emptyTreatment());
+    private final GroupBuckets indirectGroupBuckets = new GroupBuckets(ImmutableList.of(indirectBucket));
+
+    private final GroupDescription groupDesc1 =
+            new DefaultGroupDescription(did("1"), GroupDescription.Type.FAILOVER, failoverGroupBuckets);
+    private final GroupDescription groupDesc2 =
+            new DefaultGroupDescription(did("2"), GroupDescription.Type.FAILOVER, failoverGroupBuckets);
+    private final GroupDescription groupDesc3 =
+            new DefaultGroupDescription(did("3"), GroupDescription.Type.INDIRECT, indirectGroupBuckets);
 
     DefaultGroup group1 = new DefaultGroup(id1, groupDesc1);
     DefaultGroup sameAsGroup1 = new DefaultGroup(id1, groupDesc1);
@@ -83,7 +80,7 @@
         assertThat(group1.life(), is(0L));
         assertThat(group1.packets(), is(0L));
         assertThat(group1.referenceCount(), is(0L));
-        assertThat(group1.buckets(), is(groupBuckets));
+        assertThat(group1.buckets(), is(failoverGroupBuckets));
         assertThat(group1.state(), is(Group.GroupState.PENDING_ADD));
         assertThat(group1.failedRetryCount(), is(0));
     }
@@ -94,14 +91,14 @@
     @Test
     public void checkConstructionWithDid() {
         DefaultGroup group = new DefaultGroup(id2, NetTestTools.did("1"),
-                GroupDescription.Type.ALL, groupBuckets);
+                GroupDescription.Type.FAILOVER, failoverGroupBuckets);
         assertThat(group.id(), is(id2));
         assertThat(group.bytes(), is(0L));
         assertThat(group.life(), is(0L));
         assertThat(group.packets(), is(0L));
         assertThat(group.referenceCount(), is(0L));
         assertThat(group.deviceId(), is(NetTestTools.did("1")));
-        assertThat(group.buckets(), is(groupBuckets));
+        assertThat(group.buckets(), is(failoverGroupBuckets));
         assertThat(group.failedRetryCount(), is(0));
     }
 
diff --git a/core/common/src/test/java/org/onosproject/codec/impl/GroupCodecTest.java b/core/common/src/test/java/org/onosproject/codec/impl/GroupCodecTest.java
index 0867213..19c9671 100644
--- a/core/common/src/test/java/org/onosproject/codec/impl/GroupCodecTest.java
+++ b/core/common/src/test/java/org/onosproject/codec/impl/GroupCodecTest.java
@@ -76,23 +76,22 @@
 
     @Test
     public void codecEncodeTest() {
-        GroupBucket bucket1 = DefaultGroupBucket
-                .createSelectGroupBucket(DefaultTrafficTreatment.emptyTreatment());
-        GroupBucket bucket2 = DefaultGroupBucket
-                .createIndirectGroupBucket(DefaultTrafficTreatment.emptyTreatment());
-        GroupBuckets buckets = new GroupBuckets(ImmutableList.of(bucket1, bucket2));
-        GroupBuckets bucketsIndirect = new GroupBuckets(ImmutableList.of(bucket2));
+        GroupBucket bucket1 = DefaultGroupBucket.createAllGroupBucket(DefaultTrafficTreatment.emptyTreatment());
+        GroupBucket bucket2 = DefaultGroupBucket.createAllGroupBucket(DefaultTrafficTreatment.emptyTreatment());
+        GroupBucket bucket3 = DefaultGroupBucket.createIndirectGroupBucket(DefaultTrafficTreatment.emptyTreatment());
+        GroupBuckets allBuckets = new GroupBuckets(ImmutableList.of(bucket1, bucket2));
+        GroupBuckets indirectBuckets = new GroupBuckets(ImmutableList.of(bucket3));
 
         DefaultGroup group = new DefaultGroup(
                 new GroupId(1),
                 NetTestTools.did("d1"),
                 ALL,
-                buckets);
+                allBuckets);
         DefaultGroup group1 = new DefaultGroup(
                 new GroupId(2),
                 NetTestTools.did("d2"),
                 INDIRECT,
-                bucketsIndirect);
+                indirectBuckets);
 
         MockCodecContext context = new MockCodecContext();
         GroupCodec codec = new GroupCodec();
diff --git a/core/common/src/test/java/org/onosproject/utils/ComparatorsTest.java b/core/common/src/test/java/org/onosproject/utils/ComparatorsTest.java
index 6047719..d616e71 100644
--- a/core/common/src/test/java/org/onosproject/utils/ComparatorsTest.java
+++ b/core/common/src/test/java/org/onosproject/utils/ComparatorsTest.java
@@ -129,8 +129,7 @@
     private final ConnectPoint cp =
             new ConnectPoint(DeviceId.deviceId("of:00001"), PortNumber.portNumber(100));
     private final GroupBucket testBucket =
-            DefaultGroupBucket.createSelectGroupBucket(
-                    DefaultTrafficTreatment.emptyTreatment());
+            DefaultGroupBucket.createAllGroupBucket(DefaultTrafficTreatment.emptyTreatment());
     private final GroupBuckets groupBuckets =
             new GroupBuckets(ImmutableList.of(testBucket));
     private final GroupDescription groupDesc1 =
diff --git a/core/store/dist/src/test/java/org/onosproject/store/group/impl/DistributedGroupStoreTest.java b/core/store/dist/src/test/java/org/onosproject/store/group/impl/DistributedGroupStoreTest.java
index 0a44359..087bd80 100644
--- a/core/store/dist/src/test/java/org/onosproject/store/group/impl/DistributedGroupStoreTest.java
+++ b/core/store/dist/src/test/java/org/onosproject/store/group/impl/DistributedGroupStoreTest.java
@@ -61,11 +61,11 @@
 import static org.hamcrest.Matchers.notNullValue;
 import static org.hamcrest.Matchers.nullValue;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 import static org.onosproject.net.NetTestTools.APP_ID;
 import static org.onosproject.net.NetTestTools.did;
 import static org.onosproject.net.group.GroupDescription.Type.ALL;
 import static org.onosproject.net.group.GroupDescription.Type.INDIRECT;
-import static org.onosproject.net.group.GroupDescription.Type.SELECT;
 import static org.onosproject.net.group.GroupStore.UpdateType.ADD;
 import static org.onosproject.net.group.GroupStore.UpdateType.SET;
 /**
@@ -73,49 +73,49 @@
  */
 public class DistributedGroupStoreTest {
 
-    DeviceId deviceId1 = did("dev1");
-    DeviceId deviceId2 = did("dev2");
-    GroupId groupId1 = new GroupId(1);
-    GroupId groupId2 = new GroupId(2);
-    GroupId groupId3 = new GroupId(3);
-    GroupKey groupKey1 = new DefaultGroupKey("abc".getBytes());
-    GroupKey groupKey2 = new DefaultGroupKey("def".getBytes());
-    GroupKey groupKey3 = new DefaultGroupKey("ghi".getBytes());
+    private final DeviceId deviceId1 = did("dev1");
+    private final DeviceId deviceId2 = did("dev2");
+    private final GroupId groupId1 = new GroupId(1);
+    private final GroupId groupId2 = new GroupId(2);
+    private final GroupId groupId3 = new GroupId(3);
+    private final GroupKey groupKey1 = new DefaultGroupKey("abc".getBytes());
+    private final GroupKey groupKey2 = new DefaultGroupKey("def".getBytes());
+    private final GroupKey groupKey3 = new DefaultGroupKey("ghi".getBytes());
 
-    TrafficTreatment treatment =
-            DefaultTrafficTreatment.emptyTreatment();
-    GroupBucket selectGroupBucket =
-            DefaultGroupBucket.createSelectGroupBucket(treatment);
-    GroupBucket failoverGroupBucket =
-            DefaultGroupBucket.createFailoverGroupBucket(treatment,
-                    PortNumber.IN_PORT, groupId1);
+    private final TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
+    private final TrafficTreatment treatment2 = DefaultTrafficTreatment.builder()
+            .setOutput(PortNumber.portNumber(2)).build();
+    private final GroupBucket allGroupBucket = DefaultGroupBucket.createAllGroupBucket(treatment);
+    private final GroupBucket allGroupBucket2 = DefaultGroupBucket.createAllGroupBucket(treatment2);
+    private final GroupBuckets allGroupBuckets = new GroupBuckets(ImmutableList.of(allGroupBucket));
+    private final GroupBucket indirectGroupBucket = DefaultGroupBucket.createIndirectGroupBucket(treatment);
+    private final GroupBuckets indirectGroupBuckets = new GroupBuckets(ImmutableList.of(indirectGroupBucket));
 
-    GroupBuckets buckets = new GroupBuckets(ImmutableList.of(selectGroupBucket));
-    GroupDescription groupDescription1 = new DefaultGroupDescription(
+    private final GroupDescription groupDescription1 = new DefaultGroupDescription(
             deviceId1,
             ALL,
-            buckets,
+            allGroupBuckets,
             groupKey1,
             groupId1.id(),
             APP_ID);
-    GroupDescription groupDescription2 = new DefaultGroupDescription(
+    private final GroupDescription groupDescription2 = new DefaultGroupDescription(
             deviceId2,
             INDIRECT,
-            buckets,
+            indirectGroupBuckets,
             groupKey2,
             groupId2.id(),
             APP_ID);
-    GroupDescription groupDescription3 = new DefaultGroupDescription(
+    private final GroupDescription groupDescription3 = new DefaultGroupDescription(
             deviceId2,
             INDIRECT,
-            buckets,
+            indirectGroupBuckets,
             groupKey3,
             groupId3.id(),
             APP_ID);
 
-    DistributedGroupStore groupStoreImpl;
-    GroupStore groupStore;
-    ConsistentMap auditPendingReqQueue;
+    private DistributedGroupStore groupStoreImpl;
+    private GroupStore groupStore;
+    private ConsistentMap auditPendingReqQueue;
 
     static class MasterOfAll extends MastershipServiceAdapter {
         @Override
@@ -285,8 +285,8 @@
 
         GroupDescription groupDescription3 = new DefaultGroupDescription(
                 deviceId1,
-                SELECT,
-                buckets,
+                ALL,
+                allGroupBuckets,
                 new DefaultGroupKey("aaa".getBytes()),
                 null,
                 APP_ID);
@@ -347,7 +347,7 @@
         GroupOperation opAdd =
                 GroupOperation.createAddGroupOperation(groupId1,
                         INDIRECT,
-                        buckets);
+                        indirectGroupBuckets);
         groupStore.groupOperationFailed(deviceId1, opAdd);
 
         List<GroupEvent> eventsAfterAddFailed = delegate.eventsSeen();
@@ -361,7 +361,7 @@
         GroupOperation opModify =
                 GroupOperation.createModifyGroupOperation(groupId2,
                         INDIRECT,
-                        buckets);
+                        indirectGroupBuckets);
         groupStore.groupOperationFailed(deviceId2, opModify);
         List<GroupEvent> eventsAfterModifyFailed = delegate.eventsSeen();
         assertThat(eventsAfterModifyFailed, hasSize(1));
@@ -400,7 +400,7 @@
 
         // test group exists
         GroupOperation opAdd = GroupOperation
-                .createAddGroupOperation(groupId1, INDIRECT, buckets);
+                .createAddGroupOperation(groupId1, ALL, allGroupBuckets);
         GroupOperation addFailedExists = GroupOperation
                 .createFailedGroupOperation(opAdd, GroupMsgErrorCode.GROUP_EXISTS);
         groupStore.groupOperationFailed(deviceId1, addFailedExists);
@@ -420,7 +420,7 @@
         assertEquals(0, g2.failedRetryCount());
         assertEquals(GroupState.PENDING_ADD, g2.state());
         GroupOperation opAdd1 = GroupOperation
-                .createAddGroupOperation(groupId2, INDIRECT, buckets);
+                .createAddGroupOperation(groupId2, INDIRECT, indirectGroupBuckets);
         GroupOperation addFailedInvalid = GroupOperation
                 .createFailedGroupOperation(opAdd1, GroupMsgErrorCode.INVALID_GROUP);
 
@@ -487,9 +487,7 @@
      */
     @Test
     public void testUpdateGroupDescription() {
-
-        GroupBuckets buckets =
-                new GroupBuckets(ImmutableList.of(failoverGroupBucket, selectGroupBucket));
+        GroupBuckets buckets = new GroupBuckets(ImmutableList.of(allGroupBucket2));
 
         groupStore.deviceInitialAuditCompleted(deviceId1, true);
         groupStore.storeGroupDescription(groupDescription1);
@@ -504,40 +502,31 @@
         assertThat(group1.appCookie(), is(newKey));
         assertThat(group1.buckets().buckets(), hasSize(2));
 
-        short weight = 5;
-        GroupBucket selectGroupBucketWithWeight =
-                DefaultGroupBucket.createSelectGroupBucket(treatment, weight);
-        buckets = new GroupBuckets(ImmutableList.of(failoverGroupBucket,
-                selectGroupBucketWithWeight));
-
+        buckets = new GroupBuckets(ImmutableList.of(allGroupBucket, allGroupBucket2));
         groupStore.updateGroupDescription(deviceId1,
                 newKey,
                 ADD,
                 buckets,
                 newKey);
-
         group1 = groupStore.getGroup(deviceId1, groupId1);
         assertThat(group1.appCookie(), is(newKey));
         assertThat(group1.buckets().buckets(), hasSize(2));
         for (GroupBucket bucket : group1.buckets().buckets()) {
-            if (bucket.type() == SELECT) {
-                assertEquals(weight, bucket.weight());
-            }
+            assertTrue(bucket.treatment().equals(treatment) ||
+                    bucket.treatment().equals(treatment2));
         }
 
-        buckets = new GroupBuckets(ImmutableList.of(selectGroupBucketWithWeight));
-
+        buckets = new GroupBuckets(ImmutableList.of(allGroupBucket2));
         groupStore.updateGroupDescription(deviceId1,
                 newKey,
                 SET,
                 buckets,
                 newKey);
-
         group1 = groupStore.getGroup(deviceId1, groupId1);
         assertThat(group1.appCookie(), is(newKey));
         assertThat(group1.buckets().buckets(), hasSize(1));
         GroupBucket onlyBucket = group1.buckets().buckets().iterator().next();
-        assertEquals(weight, onlyBucket.weight());
+        assertEquals(treatment2, onlyBucket.treatment());
     }
 
     @Test
diff --git a/drivers/gnmi/BUILD b/drivers/gnmi/BUILD
index 50d8b5e..63b11c6 100644
--- a/drivers/gnmi/BUILD
+++ b/drivers/gnmi/BUILD
@@ -4,8 +4,7 @@
     "@io_grpc_grpc_java//netty",
     "@io_grpc_grpc_java//stub",
     "//core/store/serializers:onos-core-serializers",
-    "//protocols/gnmi/stub:gnmi_java_grpc",
-    "//protocols/gnmi/stub:gnmi_java_proto",
+    "//protocols/gnmi/stub:onos-protocols-gnmi-stub",
     "//protocols/grpc/api:onos-protocols-grpc-api",
     "//protocols/grpc/proto:onos-protocols-grpc-proto",
 ]
diff --git a/modules.defs b/modules.defs
new file mode 100644
index 0000000..b4097c7
--- /dev/null
+++ b/modules.defs
@@ -0,0 +1,326 @@
+UTILS = [
+    '//utils/osgi:onlab-osgi',
+    '//utils/junit:onlab-junit',
+    '//utils/misc:onlab-misc',
+    '//utils/rest:onlab-rest',
+    '//tools/build/conf:onos-build-conf',
+]
+
+API = [
+    '//core/api:onos-api',
+    '//incubator/api:onos-incubator-api',
+]
+
+CORE = UTILS + API + [
+    '//core/net:onos-core-net',
+    '//core/common:onos-core-common',
+    '//core/store/primitives:onos-core-primitives',
+    '//core/store/serializers:onos-core-serializers',
+    '//core/store/dist:onos-core-dist',
+    '//core/security:onos-security',
+    '//core/store/persistence:onos-core-persistence',
+
+    '//incubator/net:onos-incubator-net',
+    '//incubator/store:onos-incubator-store',
+    '//incubator/rpc:onos-incubator-rpc',
+
+    '//cli:onos-cli',
+
+    '//protocols/rest/api:onos-protocols-rest-api',
+    '//protocols/rest/ctl:onos-protocols-rest-ctl',
+    '//protocols/bgp/bgpio:onos-protocols-bgp-bgpio',
+    '//protocols/bgp/api:onos-protocols-bgp-api',
+    '//protocols/bgp/ctl:onos-protocols-bgp-ctl',
+    # '//protocols/bmv2/thrift-api:onos-protocols-bmv2-thrift-api',
+    '//protocols/netconf/api:onos-protocols-netconf-api',
+    '//protocols/netconf/ctl:onos-protocols-netconf-ctl',
+    '//protocols/openflow/api:onos-protocols-openflow-api',
+    '//protocols/openflow/ctl:onos-protocols-openflow-ctl',
+    '//protocols/ospf/api:onos-protocols-ospf-api',
+    '//protocols/ospf/protocol:onos-protocols-ospf-protocol',
+    '//protocols/ospf/ctl:onos-protocols-ospf-ctl',
+    '//protocols/ovsdb/rfc:onos-protocols-ovsdb-rfc',
+    '//protocols/ovsdb/api:onos-protocols-ovsdb-api',
+    '//protocols/ovsdb/ctl:onos-protocols-ovsdb-ctl',
+    '//protocols/pcep/pcepio:onos-protocols-pcep-pcepio',
+    '//protocols/pcep/server/api:onos-protocols-pcep-server-api',
+    '//protocols/pcep/server/ctl:onos-protocols-pcep-server-ctl',
+    '//protocols/snmp/api:onos-protocols-snmp-api',
+    '//protocols/snmp/ctl:onos-protocols-snmp-ctl',
+    '//protocols/isis/api:onos-protocols-isis-api',
+    '//protocols/isis/ctl:onos-protocols-isis-ctl',
+    '//protocols/isis/isisio:onos-protocols-isis-isisio',
+    '//protocols/lisp/api:onos-protocols-lisp-api',
+    '//protocols/lisp/ctl:onos-protocols-lisp-ctl',
+    '//protocols/lisp/msg:onos-protocols-lisp-msg',
+    '//protocols/tl1/api:onos-protocols-tl1-api',
+    '//protocols/tl1/ctl:onos-protocols-tl1-ctl',
+    '//protocols/restconf/client/api:onos-protocols-restconf-client-api',
+    '//protocols/restconf/client/ctl:onos-protocols-restconf-client-ctl',
+    '//protocols/xmpp/core/api:onos-protocols-xmpp-core-api',
+    '//protocols/xmpp/core/ctl:onos-protocols-xmpp-core-ctl',
+
+    '//drivers/utilities:onos-drivers-utilities',
+
+    '//providers/netconf/device:onos-providers-netconf-device',
+    '//providers/openflow/device:onos-providers-openflow-device',
+    '//providers/openflow/packet:onos-providers-openflow-packet',
+    '//providers/openflow/flow:onos-providers-openflow-flow',
+    '//providers/openflow/group:onos-providers-openflow-group',
+    '//providers/openflow/meter:onos-providers-openflow-meter',
+    '//providers/ovsdb/device:onos-providers-ovsdb-device',
+    '//providers/ovsdb/tunnel:onos-providers-ovsdb-tunnel',
+    '//providers/rest/device:onos-providers-rest-device',
+    '//providers/snmp/device:onos-providers-snmp-device',
+    '//providers/isis/cfg:onos-providers-isis-cfg',
+    '//providers/isis/topology:onos-providers-isis-topology',
+    '//providers/lisp/device:onos-providers-lisp-device',
+    '//providers/tl1/device:onos-providers-tl1-device',
+    '//providers/general/device:onos-providers-general-device',
+    # '//providers/p4runtime/packet:onos-providers-p4runtime-packet',
+
+    '//web/api:onos-rest',
+    # '//web/gui2:onos-gui2',
+    '//web/gui:onos-gui',
+
+    '//incubator/protobuf/models:onos-incubator-protobuf-models',
+    '//incubator/protobuf/services/nb:onos-incubator-protobuf-services-nb',
+]
+
+ONOS_DRIVERS = [
+    # Drivers
+    '//drivers/default:onos-drivers-default-oar',
+    '//drivers/arista:onos-drivers-arista-oar',
+    '//drivers/ciena/waveserver:onos-drivers-ciena-waveserver-oar',
+    '//drivers/ciena/c5162:onos-drivers-ciena-c5162-oar',
+    '//drivers/ciena/c5170:onos-drivers-ciena-c5170-oar',
+    '//drivers/ciena/waveserverai:onos-drivers-ciena-waveserverai-oar',
+    '//drivers/cisco/netconf:onos-drivers-cisco-netconf-oar',
+    '//drivers/cisco/rest:onos-drivers-cisco-rest-oar',
+    '//drivers/corsa:onos-drivers-corsa-oar',
+    '//drivers/fujitsu:onos-drivers-fujitsu-oar',
+    '//drivers/lumentum:onos-drivers-lumentum-oar',
+    '//drivers/netconf:onos-drivers-netconf-oar',
+    '//drivers/server:onos-drivers-server-oar',
+    '//drivers/optical:onos-drivers-optical-oar',
+    '//drivers/ovsdb:onos-drivers-ovsdb-oar',
+    '//drivers/juniper:onos-drivers-juniper-oar',
+    '//drivers/lisp:onos-drivers-lisp-oar',
+    '//drivers/flowspec:onos-drivers-flowspec-oar',
+    '//drivers/huawei:onos-drivers-huawei-oar',
+    '//drivers/microsemi/ea1000:onos-drivers-microsemi-ea1000-oar',
+    '//drivers/oplink:onos-drivers-oplink-oar',
+    # '//drivers/bmv2:onos-drivers-bmv2-oar',
+    # '//drivers/barefoot:onos-drivers-barefoot-oar',
+    # '//drivers/mellanox:onos-drivers-mellanox-oar',
+    '//drivers/hp:onos-drivers-hp-oar',
+    # '//drivers/p4runtime:onos-drivers-p4runtime-oar',
+    # '//drivers/gnmi:onos-drivers-gnmi-oar',
+    '//drivers/polatis/netconf:onos-drivers-polatis-netconf-oar',
+    '//drivers/polatis/openflow:onos-drivers-polatis-openflow-oar',
+    '//drivers/polatis/snmp:onos-drivers-polatis-snmp-oar',
+    '//drivers/odtn-driver:onos-drivers-odtn-driver-oar',
+]
+
+ONOS_PROVIDERS = [
+    # Providers
+    '//providers/bgp:onos-providers-bgp-oar',
+    '//providers/bgpcep:onos-providers-bgpcep-oar',
+    '//providers/host:onos-providers-host-oar',
+    '//providers/hostprobing:onos-providers-hostprobing-oar',
+    '//providers/lldp:onos-providers-lldp-oar',
+    '//providers/netcfghost:onos-providers-netcfghost-oar',
+    '//providers/netcfglinks:onos-providers-netcfglinks-oar',
+    '//providers/netconf:onos-providers-netconf-oar',
+    '//providers/openflow/message:onos-providers-openflow-message-oar',
+    '//providers/ovsdb:onos-providers-ovsdb-oar',
+    '//providers/ovsdb/host:onos-providers-ovsdb-host-oar',
+    '//providers/ovsdb/base:onos-providers-ovsdb-base-oar',
+    '//providers/pcep:onos-providers-pcep-oar',
+    '//providers/null:onos-providers-null-oar',
+    '//providers/openflow/base:onos-providers-openflow-base-oar',
+    '//providers/openflow/app:onos-providers-openflow-app-oar',
+    '//providers/rest:onos-providers-rest-oar',
+    '//providers/isis:onos-providers-isis-oar',
+    '//providers/snmp:onos-providers-snmp-oar',
+    '//providers/link:onos-providers-link-oar',
+    '//providers/lisp:onos-providers-lisp-oar',
+    '//providers/tl1:onos-providers-tl1-oar',
+    '//providers/general:onos-providers-general-oar',
+    # '//providers/p4runtime:onos-providers-p4runtime-oar',
+#    '//providers/ietfte:onos-providers-ietfte-oar',
+    '//providers/xmpp/device:onos-providers-xmpp-device-oar',
+]
+
+ONOS_APPS = [
+    # Apps
+    '//apps/dhcp:onos-apps-dhcp-oar',
+    '//apps/dhcprelay:onos-apps-dhcprelay-oar',
+    '//apps/fwd:onos-apps-fwd-oar',
+    '//apps/packet-stats:onos-apps-packet-stats-oar',
+    '//apps/acl:onos-apps-acl-oar',
+    '//apps/bgprouter:onos-apps-bgprouter-oar',
+    '//apps/cip:onos-apps-cip-oar',
+    '//apps/drivermatrix:onos-apps-drivermatrix-oar',
+    '//apps/events:onos-apps-events-oar',
+    '//apps/proxyarp:onos-apps-proxyarp-oar',
+    '//apps/segmentrouting:onos-apps-segmentrouting-oar',
+    '//apps/gangliametrics:onos-apps-gangliametrics-oar',
+    '//apps/graphitemetrics:onos-apps-graphitemetrics-oar',
+    '//apps/flowanalyzer:onos-apps-flowanalyzer-oar',
+    '//apps/intentsync:onos-apps-intentsync-oar',
+    '//apps/influxdbmetrics:onos-apps-influxdbmetrics-oar',
+    '//apps/metrics:onos-apps-metrics-oar',
+    '//apps/mfwd:onos-apps-mfwd-oar',
+    '//apps/mlb:onos-apps-mlb-oar',
+    '//apps/openstacknetworking:onos-apps-openstacknetworking-oar',
+    '//apps/mobility:onos-apps-mobility-oar',
+    '//apps/newoptical:onos-apps-newoptical-oar',
+    '//apps/optical-model:onos-apps-optical-model-oar',
+    '//apps/optical-rest:onos-apps-optical-rest-oar',
+    '//apps/pathpainter:onos-apps-pathpainter-oar',
+    '//apps/pcep-api:onos-apps-pcep-api-oar',
+    '//apps/pim:onos-apps-pim-oar',
+    '//apps/linkprops:onos-apps-linkprops-oar',
+    '//apps/reactive-routing:onos-apps-reactive-routing-oar',
+    '//apps/roadm:onos-apps-roadm-oar',
+    '//apps/sdnip:onos-apps-sdnip-oar',
+    '//apps/test/cluster-ha:onos-apps-test-cluster-ha-oar',
+    '//apps/test/demo:onos-apps-test-demo-oar',
+    '//apps/test/distributed-primitives:onos-apps-test-distributed-primitives-oar',
+    '//apps/test/election:onos-apps-test-election-oar',
+    '//apps/test/flow-perf:onos-apps-test-flow-perf-oar',
+    '//apps/test/intent-perf:onos-apps-test-intent-perf-oar',
+    '//apps/test/route-scale:onos-apps-test-route-scale-oar',
+    '//apps/test/loadtest:onos-apps-test-loadtest-oar',
+    '//apps/test/netcfg-monitor:onos-apps-test-netcfg-monitor-oar',
+    '//apps/test/messaging-perf:onos-apps-test-messaging-perf-oar',
+    '//apps/test/primitive-perf:onos-apps-test-primitive-perf-oar',
+    '//apps/test/proxy:onos-apps-test-proxy-oar',
+    '//apps/test/transaction-perf:onos-apps-test-transaction-perf-oar',
+    '//apps/virtualbng:onos-apps-virtualbng-oar',
+    '//apps/vpls:onos-apps-vpls-oar',
+    '//apps/vrouter:onos-apps-vrouter-oar',
+    '//apps/routing/fibinstaller:onos-apps-routing-fibinstaller-oar',
+    '//apps/routing/cpr:onos-apps-routing-cpr-oar',
+    '//apps/routing/fpm:onos-apps-routing-fpm-oar',
+    '//apps/vtn:onos-apps-vtn-oar',
+    '//apps/faultmanagement:onos-apps-faultmanagement-oar',
+    '//apps/openstacknode:onos-apps-openstacknode-oar',
+    '//apps/cpman/app:onos-apps-cpman-app-oar',
+    '//apps/scalablegateway:onos-apps-scalablegateway-oar',
+    '//apps/castor:onos-apps-castor-oar',
+#    '//apps/yms:onos-apps-yms-oar',
+    '//apps/ofagent:onos-apps-ofagent-oar',
+    '//apps/mappingmanagement:onos-apps-mappingmanagement-oar',
+    '//apps/config:onos-apps-config-oar',
+    '//apps/configsync:onos-apps-configsync-oar',
+    '//apps/configsync-netconf:onos-apps-configsync-netconf-oar',
+    '//apps/netconf/client:onos-apps-netconf-client-oar',
+    '//apps/tetopology:onos-apps-tetopology-oar',
+    '//apps/tetunnel:onos-apps-tetunnel-oar',
+#    '//apps/tenbi/yangmodel:onos-apps-tenbi-yangmodel-feature',
+#    '//apps/tenbi:onos-apps-tenbi-oar',
+    '//protocols/restconf/server:onos-protocols-restconf-server-oar',
+    '//apps/restconf:onos-apps-restconf-oar',
+    '//apps/flowspec-api:onos-apps-flowspec-api-oar',
+    '//apps/yang:onos-apps-yang-oar',
+    '//apps/yang-gui:onos-apps-yang-gui-oar',
+    '//apps/cord-support:onos-apps-cord-support-oar',
+    '//apps/network-troubleshoot:onos-apps-network-troubleshoot-oar',
+    '//apps/l3vpn:onos-apps-l3vpn-oar',
+    '//apps/openroadm:onos-apps-openroadm-oar',
+    '//apps/artemis:onos-apps-artemis-oar',
+    '//apps/pi-demo/ecmp:onos-apps-pi-demo-ecmp-oar',
+    '//apps/gluon:onos-apps-gluon-oar',
+    '//apps/evpnopenflow:onos-apps-evpnopenflow-oar',
+    '//apps/route-service:onos-apps-route-service-oar',
+    '//apps/evpn-route-service:onos-apps-evpn-route-service-oar',
+    '//incubator/protobuf/registry:onos-incubator-protobuf-registry-oar',
+    '//incubator/protobuf/services/nb:onos-incubator-protobuf-services-nb-oar',
+    '//apps/openstacknetworkingui:onos-apps-openstacknetworkingui-oar',
+    '//apps/openstacktelemetry:onos-apps-openstacktelemetry-oar',
+    '//apps/openstacktroubleshoot:onos-apps-openstacktroubleshoot-oar',
+    '//apps/openstackvtap:onos-apps-openstackvtap-oar',
+    # '//apps/p4-tutorial/pipeconf:onos-apps-p4-tutorial-pipeconf-oar',
+    # '//apps/p4-tutorial/mytunnel:onos-apps-p4-tutorial-mytunnel-oar',
+    '//apps/cfm:onos-apps-cfm-oar',
+    '//apps/routeradvertisement:onos-apps-routeradvertisement-oar',
+    '//apps/powermanagement:onos-apps-powermanagement-oar',
+    '//apps/t3:onos-apps-t3-oar',
+    '//apps/simplefabric:onos-apps-simplefabric-oar',
+    '//apps/kafka-integration:onos-apps-kafka-integration-oar',
+    '//apps/rabbitmq:onos-apps-rabbitmq-oar',
+    '//apps/odtn/api:onos-apps-odtn-api-oar',
+    '//apps/odtn/service:onos-apps-odtn-service-oar',
+    '//apps/mcast:onos-apps-mcast-oar',
+    '//apps/layout:onos-apps-layout-oar',
+    '//apps/imr:onos-apps-imr-oar',
+    '//apps/inbandtelemetry/app:onos-apps-inbandtelemetry-app-oar',
+    '//apps/workflow:onos-apps-workflow-oar',
+    # nodemetrics application
+    '//apps/nodemetrics:onos-apps-nodemetrics-oar',
+    #'//web/gui2:onos-web-gui2-oar',
+]
+
+PROTOCOL_APPS = [
+    # '//protocols/grpc:onos-protocols-grpc-oar',
+    # '//protocols/p4runtime:onos-protocols-p4runtime-oar',
+    #'//protocols/gnmi:onos-protocols-gnmi-oar',
+    '//protocols/xmpp/core:onos-protocols-xmpp-core-oar',
+    '//protocols/xmpp/pubsub:onos-protocols-xmpp-pubsub-oar',
+]
+
+MODELS = [
+    '//models/ietf:onos-models-ietf-oar',
+    '//models/common:onos-models-common-oar',
+    '//models/huawei:onos-models-huawei-oar',
+    '//models/openconfig:onos-models-openconfig-oar',
+    '//models/openconfig-infinera:onos-models-openconfig-infinera-oar',
+    '//models/openroadm:onos-models-openroadm-oar',
+    '//models/tapi:onos-models-tapi-oar',
+    '//models/l3vpn:onos-models-l3vpn-oar',
+    '//models/microsemi:onos-models-microsemi-oar',
+    '//models/polatis:onos-models-polatis-oar',
+    '//models/ciena/waveserverai:onos-models-ciena-waveserverai-oar',
+]
+
+PIPELINES = [
+    # '//pipelines/basic:onos-pipelines-basic-oar',
+    # '//pipelines/fabric:onos-pipelines-fabric-oar',
+]
+
+APP_JARS = [
+    '//apps/cpman/api:onos-apps-cpman-api',
+    '//apps/routing-api:onos-apps-routing-api',
+    '//apps/dhcp/api:onos-apps-dhcp-api',
+    '//apps/dhcp/app:onos-apps-dhcp-app',
+    '//apps/imr/api:onos-apps-imr-api',
+    '//apps/imr/app:onos-apps-imr-app',
+    '//apps/dhcprelay:onos-apps-dhcprelay',
+    '//apps/fwd:onos-apps-fwd',
+    '//apps/iptopology-api:onos-apps-iptopology-api',
+    '//apps/routing/common:onos-apps-routing-common',
+    '//apps/vtn/vtnrsc:onos-apps-vtn-vtnrsc',
+    '//apps/vtn/sfcmgr:onos-apps-vtn-sfcmgr',
+    '//apps/vtn/vtnmgr:onos-apps-vtn-vtnmgr',
+    '//apps/vtn/vtnweb:onos-apps-vtn-vtnweb',
+    '//apps/kafka-integration/api:onos-apps-kafka-integration-api',
+    '//apps/kafka-integration/app:onos-apps-kafka-integration-app',
+]
+
+FEATURES = [
+  '//tools/package/features:onos-thirdparty-base',
+  '//tools/package/features:onos-thirdparty-web',
+  '//tools/package/features:onos-api',
+  '//tools/package/features:onos-core',
+  '//tools/package/features:onos-incubator',
+  '//tools/package/features:onos-rest',
+  '//tools/package/features:onos-gui',
+  #'//tools/package/features:onos-gui2',
+  '//tools/package/features:onos-cli',
+  '//tools/package/features:onos-security',
+]
+
+APPS = ONOS_DRIVERS + ONOS_PROVIDERS + ONOS_APPS + MODELS + PIPELINES \
+        + PROTOCOL_APPS
diff --git a/protocols/gnmi/BUILD b/protocols/gnmi/BUILD
index 30599ae..8a3510d 100644
--- a/protocols/gnmi/BUILD
+++ b/protocols/gnmi/BUILD
@@ -1,6 +1,5 @@
 BUNDLES = [
-    "//protocols/gnmi/stub:gnmi_java_grpc",
-    "//protocols/gnmi/stub:gnmi_java_proto",
+    "//protocols/gnmi/stub:onos-protocols-gnmi-stub",
 ]
 
 onos_app(
diff --git a/protocols/gnmi/stub/BUILD b/protocols/gnmi/stub/BUILD
index 3b1a2dc..cf79265 100644
--- a/protocols/gnmi/stub/BUILD
+++ b/protocols/gnmi/stub/BUILD
@@ -1,43 +1,14 @@
-load("//tools/build/bazel:osgi_java_library.bzl", "wrapped_osgi_jar")
-load("@io_grpc_grpc_java//:java_grpc_library.bzl", "java_grpc_library")
+load("//tools/build/bazel:osgi_java_library.bzl", "osgi_proto_jar")
 
-wrapped_osgi_jar(
-    name = "gnmi_java_grpc",
-    jar = ":gnmi_java_grpc_native",
-    visibility = ["//visibility:public"],
+PROTOS = [
+    "@com_github_openconfig_gnmi//:gnmi_proto",
+    "@com_github_openconfig_gnmi//:gnmi_ext_proto",
+]
+
+osgi_proto_jar(
+    grpc_proto_lib = "@com_github_openconfig_gnmi//:gnmi_proto",
+    proto_libs = PROTOS,
     deps = [
-        "@io_grpc_grpc_java//core",
-        "@io_grpc_grpc_java//protobuf",
-        "@io_grpc_grpc_java//stub",
-    ],
-)
-
-wrapped_osgi_jar(
-    name = "gnmi_java_proto",
-    jar = ":gnmi_java_proto_native",
-    visibility = ["//visibility:public"],
-    deps = [
-        "@com_google_protobuf//:protobuf_java",
-    ],
-)
-
-java_proto_library(
-    name = "gnmi_java_proto_native",
-    visibility = ["//visibility:public"],
-    deps = [":gnmi_proto"],
-)
-
-java_grpc_library(
-    name = "gnmi_java_grpc_native",
-    srcs = [":gnmi_proto"],
-    deps = [":gnmi_java_proto_native"],
-)
-
-proto_library(
-    name = "gnmi_proto",
-    srcs = ["src/main/proto/gnmi.proto"],
-    deps = [
-        "@com_google_protobuf//:any_proto",
-        "@com_google_protobuf//:descriptor_proto",
+        "@com_google_api_grpc_proto_google_common_protos//jar",
     ],
 )
diff --git a/protocols/gnmi/stub/src/main/proto/COMMIT_ID b/protocols/gnmi/stub/src/main/proto/COMMIT_ID
deleted file mode 100644
index acf773d..0000000
--- a/protocols/gnmi/stub/src/main/proto/COMMIT_ID
+++ /dev/null
@@ -1,2 +0,0 @@
-https://github.com/openconfig/gnmi/blob/master/proto/gnmi/gnmi.proto
-9c8d9e965b3e854107ea02c12ab11b70717456f2
diff --git a/protocols/gnmi/stub/src/main/proto/gnmi.proto b/protocols/gnmi/stub/src/main/proto/gnmi.proto
deleted file mode 100644
index 1f3bb7c..0000000
--- a/protocols/gnmi/stub/src/main/proto/gnmi.proto
+++ /dev/null
@@ -1,423 +0,0 @@
-//
-// Copyright 2016 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//    http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-syntax = "proto3";
-
-import "google/protobuf/any.proto";
-import "google/protobuf/descriptor.proto";
-
-// Package gNMI defines a service specification for the gRPC Network Management
-// Interface. This interface is defined to be a standard interface via which
-// a network management system ("client") can subscribe to state values,
-// retrieve snapshots of state information, and manipulate the state of a data
-// tree supported by a device ("target").
-//
-// This document references the gNMI Specification which can be found at
-// http://github.com/openconfig/reference/blob/master/rpc/gnmi
-package gnmi;
-
-// Define a protobuf FileOption that defines the gNMI service version.
-extend google.protobuf.FileOptions {
-    // The gNMI service semantic version.
-    string gnmi_service = 1001;
-}
-
-// gNMI_service is the current version of the gNMI service, returned through
-// the Capabilities RPC.
-option (gnmi_service) = "0.5.0";
-
-service gNMI {
-    // Capabilities allows the client to retrieve the set of capabilities that
-    // is supported by the target. This allows the target to validate the
-    // service version that is implemented and retrieve the set of models that
-    // the target supports. The models can then be specified in subsequent RPCs
-    // to restrict the set of data that is utilized.
-    // Reference: gNMI Specification Section 3.2
-    rpc Capabilities(CapabilityRequest) returns (CapabilityResponse);
-    // Retrieve a snapshot of data from the target. A Get RPC requests that the
-    // target snapshots a subset of the data tree as specified by the paths
-    // included in the message and serializes this to be returned to the
-    // client using the specified encoding.
-    // Reference: gNMI Specification Section 3.3
-    rpc Get(GetRequest) returns (GetResponse);
-    // Set allows the client to modify the state of data on the target. The
-    // paths to modified along with the new values that the client wishes
-    // to set the value to.
-    // Reference: gNMI Specification Section 3.4
-    rpc Set(SetRequest) returns (SetResponse);
-    // Subscribe allows a client to request the target to send it values
-    // of particular paths within the data tree. These values may be streamed
-    // at a particular cadence (STREAM), sent one off on a long-lived channel
-    // (POLL), or sent as a one-off retrieval (ONCE).
-    // Reference: gNMI Specification Section 3.5
-    rpc Subscribe(stream SubscribeRequest) returns (stream SubscribeResponse);
-}
-
-// Notification is a re-usable message that is used to encode data from the
-// target to the client. A Notification carries two types of changes to the data
-// tree:
-//  - Deleted values (delete) - a set of paths that have been removed from the
-//    data tree.
-//  - Updated values (update) - a set of path-value pairs indicating the path
-//    whose value has changed in the data tree.
-// Reference: gNMI Specification Section 2.1
-message Notification {
-    int64 timestamp = 1;          // Timestamp in nanoseconds since Epoch.
-    Path prefix = 2;              // Prefix used for paths in the message.
-    // An alias for the path specified in the prefix field.
-    // Reference: gNMI Specification Section 2.4.2
-    string alias = 3;
-    repeated Update update = 4;   // Data elements that have changed values.
-    repeated Path delete = 5;     // Data elements that have been deleted.
-}
-
-// Update is a re-usable message that is used to store a particular Path,
-// Value pair.
-// Reference: gNMI Specification Section 2.1
-message Update {
-    Path path = 1;                      // The path (key) for the update.
-    Value value = 2 [deprecated=true];  // The value (value) for the update.
-    TypedValue val = 3;                 // The explicitly typed update value.
-    uint32 duplicates = 4;              // Number of coalesced duplicates.
-}
-
-// TypedValue is used to encode a value being sent between the client and
-// target (originated by either entity).
-message TypedValue {
-    // One of the fields within the val oneof is populated with the value
-    // of the update. The type of the value being included in the Update
-    // determines which field should be populated. In the case that the
-    // encoding is a particular form of the base protobuf type, a specific
-    // field is used to store the value (e.g., json_val).
-    oneof value {
-        string string_val = 1;            // String value.
-        int64 int_val = 2;                // Integer value.
-        uint64 uint_val = 3;              // Unsigned integer value.
-        bool bool_val = 4;                // Bool value.
-        bytes bytes_val = 5;              // Arbitrary byte sequence value.
-        float float_val = 6;              // Floating point value.
-        Decimal64 decimal_val = 7;        // Decimal64 encoded value.
-        ScalarArray leaflist_val = 8;     // Mixed type scalar array value.
-        google.protobuf.Any any_val = 9;  // protobuf.Any encoded bytes.
-        bytes json_val = 10;              // JSON-encoded text.
-        bytes json_ietf_val = 11;         // JSON-encoded text per RFC7951.
-        string ascii_val = 12;            // Arbitrary ASCII text.
-    }
-}
-
-// Path encodes a data tree path as a series of repeated strings, with
-// each element of the path representing a data tree node name and the
-// associated attributes.
-// Reference: gNMI Specification Section 2.2.2.
-message Path {
-    // Elements of the path are no longer encoded as a string, but rather within
-    // the elem field as a PathElem message.
-    repeated string element = 1 [deprecated=true];
-    string origin = 2;                              // Label to disambiguate path.
-    repeated PathElem elem = 3;                     // Elements of the path.
-    string target = 4;                              // The name of the target
-    // (Sec. 2.2.2.1)
-}
-
-// PathElem encodes an element of a gNMI path, along ith any attributes (keys)
-// that may be associated with it.
-// Reference: gNMI Specification Section 2.2.2.
-message PathElem {
-    string name = 1;                    // The name of the element in the path.
-    map<string, string> key = 2;        // Map of key (attribute) name to value.
-}
-
-// Value encodes a data tree node's value - along with the way in which
-// the value is encoded. This message is deprecated by gNMI 0.3.0.
-// Reference: gNMI Specification Section 2.2.3.
-message Value {
-    option deprecated = true;
-    bytes value = 1;      // Value of the variable being transmitted.
-    Encoding type = 2;    // Encoding used for the value field.
-}
-
-// Encoding defines the value encoding formats that are supported by the gNMI
-// protocol. These encodings are used by both the client (when sending Set
-// messages to modify the state of the target) and the target when serializing
-// data to be returned to the client (in both Subscribe and Get RPCs).
-// Reference: gNMI Specification Section 2.3
-enum Encoding {
-    JSON = 0;           // JSON encoded text.
-    BYTES = 1;          // Arbitrarily encoded bytes.
-    PROTO = 2;          // Encoded according to out-of-band agreed Protobuf.
-    ASCII = 3;          // ASCII text of an out-of-band agreed format.
-    JSON_IETF = 4;      // JSON encoded text as per RFC7951.
-}
-
-// Error message previously utilised to return errors to the client. Deprecated
-// in favour of using the google.golang.org/genproto/googleapis/rpc/status
-// message in the RPC response.
-// Reference: gNMI Specification Section 2.5
-message Error {
-    option deprecated = true;
-    uint32 code = 1;                // Canonical gRPC error code.
-    string message = 2;             // Human readable error.
-    google.protobuf.Any data = 3;   // Optional additional information.
-}
-
-// Decimal64 is used to encode a fixed precision decimal number. The value
-// is expressed as a set of digits with the precision specifying the
-// number of digits following the decimal point in the digit set.
-message Decimal64 {
-    int64 digits = 1;         // Set of digits.
-    uint32 precision = 2;     // Number of digits following the decimal point.
-}
-
-// ScalarArray is used to encode a mixed-type array of values.
-message ScalarArray {
-    // The set of elements within the array. Each TypedValue message should
-    // specify only elements that have a field identifier of 1-7 (i.e., the
-    // values are scalar values).
-    repeated TypedValue element = 1;
-}
-
-// SubscribeRequest is the message sent by the client to the target when
-// initiating a subscription to a set of paths within the data tree. The
-// request field must be populated and the initial message must specify a
-// SubscriptionList to initiate a subscription. The message is subsequently
-// used to define aliases or trigger polled data to be sent by the target.
-// Reference: gNMI Specification Section 3.5.1.1
-message SubscribeRequest {
-    oneof request {
-        SubscriptionList subscribe = 1; // Specify the paths within a subscription.
-        Poll poll = 3;                  // Trigger a polled update.
-        AliasList aliases = 4;          // Aliases to be created.
-    }
-}
-
-// Poll is sent within a SubscribeRequest to trigger the device to
-// send telemetry updates for the paths that are associated with the
-// subscription.
-// Reference: gNMI Specification Section Section 3.5.1.4
-message Poll {
-}
-
-// SubscribeResponse is the message used by the target within a Subscribe RPC.
-// The target includes a Notification message which is used to transmit values
-// of the path(s) that are associated with the subscription. The same message
-// is to indicate that the target has sent all data values once (is
-// synchronized).
-// Reference: gNMI Specification Section 3.5.1.4
-message SubscribeResponse {
-    oneof response {
-        Notification update = 1;          // Changed or sampled value for a path.
-        // Indicate target has sent all values associated with the subscription
-        // at least once.
-        bool sync_response = 3;
-        // Deprecated in favour of google.golang.org/genproto/googleapis/rpc/status
-        Error error = 4 [deprecated=true];
-    }
-}
-
-// SubscriptionList is used within a Subscribe message to specify the list of
-// paths that the client wishes to subscribe to. The message consists of a
-// list of (possibly prefixed) paths, and options that relate to the
-// subscription.
-// Reference: gNMI Specification Section 3.5.1.2
-message SubscriptionList {
-    Path prefix = 1;                          // Prefix used for paths.
-    repeated Subscription subscription = 2;   // Set of subscriptions to create.
-    // Whether target defined aliases are allowed within the subscription.
-    bool use_aliases = 3;
-    QOSMarking qos = 4;                       // DSCP marking to be used.
-    // Mode of the subscription.
-    enum Mode {
-        STREAM = 0; // Values streamed by the target (Sec. 3.5.1.5.2).
-        ONCE = 1;   // Values sent once-off by the target (Sec. 3.5.1.5.1).
-        POLL = 2;   // Values sent in response to a poll request (Sec. 3.5.1.5.3).
-    }
-    Mode mode = 5;
-    // Whether elements of the schema that are marked as eligible for aggregation
-    // should be aggregated or not.
-    bool allow_aggregation = 6;
-    // The set of schemas that define the elements of the data tree that should
-    // be sent by the target.
-    repeated ModelData use_models = 7;
-    // The encoding that the target should use within the Notifications generated
-    // corresponding to the SubscriptionList.
-    Encoding encoding = 8;
-    // An optional field to specify that only updates to current state should be
-    // sent to a client. If set, the initial state is not sent to the client but
-    // rather only the sync message followed by any subsequent updates to the
-    // current state. For ONCE and POLL modes, this causes the server to send only
-    // the sync message (Sec. 3.5.2.3).
-    bool updates_only = 9;
-}
-
-// Subscription is a single request within a SubscriptionList. The path
-// specified is interpreted (along with the prefix) as the elements of the data
-// tree that the client is subscribing to. The mode determines how the target
-// should trigger updates to be sent.
-// Reference: gNMI Specification Section 3.5.1.3
-message Subscription {
-    Path path = 1;                    // The data tree path.
-    SubscriptionMode mode = 2;        // Subscription mode to be used.
-    uint64 sample_interval = 3;       // ns between samples in SAMPLE mode.
-    // Indicates whether values that not changed should be sent in a SAMPLE
-    // subscription.
-    bool suppress_redundant = 4;
-    // Specifies the maximum allowable silent period in nanoseconds when
-    // suppress_redundant is in use. The target should send a value at least once
-    // in the period specified.
-    uint64 heartbeat_interval = 5;
-}
-
-// SubscriptionMode is the mode of the subscription, specifying how the
-// target must return values in a subscription.
-// Reference: gNMI Specification Section 3.5.1.3
-enum SubscriptionMode {
-    TARGET_DEFINED = 0;  // The target selects the relevant mode for each element.
-    ON_CHANGE      = 1;  // The target sends an update on element value change.
-    SAMPLE         = 2;  // The target samples values according to the interval.
-}
-
-// QOSMarking specifies the DSCP value to be set on transmitted telemetry
-// updates from the target.
-// Reference: gNMI Specification Section 3.5.1.2
-message QOSMarking {
-    uint32 marking = 1;
-}
-
-// Alias specifies a data tree path, and an associated string which defines an
-// alias which is to be used for this path in the context of the RPC. The alias
-// is specified as a string which is prefixed with "#" to disambiguate it from
-// data tree element paths.
-// Reference: gNMI Specification Section 2.4.2
-message Alias {
-    Path path = 1;     // The path to be aliased.
-    string alias = 2;  // The alias value, a string prefixed by "#".
-}
-
-// AliasList specifies a list of aliases. It is used in a SubscribeRequest for
-// a client to create a set of aliases that the target is to utilize.
-// Reference: gNMI Specification Section 3.5.1.6
-message AliasList {
-    repeated Alias alias = 1;    // The set of aliases to be created.
-}
-
-// SetRequest is sent from a client to the target to update values in the data
-// tree. Paths are either deleted by the client, or modified by means of being
-// updated, or replaced. Where a replace is used, unspecified values are
-// considered to be replaced, whereas when update is used the changes are
-// considered to be incremental. The set of changes that are specified within
-// a single SetRequest are considered to be a transaction.
-// Reference: gNMI Specification Section 3.4.1
-message SetRequest {
-    Path prefix = 1;                // Prefix used for paths in the message.
-    repeated Path delete = 2;       // Paths to be deleted from the data tree.
-    repeated Update replace = 3;    // Updates specifying elements to be replaced.
-    repeated Update update = 4;     // Updates specifying elements to updated.
-}
-
-// SetResponse is the response to a SetRequest, sent from the target to the
-// client. It reports the result of the modifications to the data tree that were
-// specified by the client. Errors for this RPC should be reported using the
-// https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto
-// message in the RPC return. The gnmi.Error message can be used to add additional
-// details where required.
-// Reference: gNMI Specification Section 3.4.2
-message SetResponse {
-    Path prefix = 1;                      // Prefix used for paths.
-    // A set of responses specifying the result of the operations specified in
-    // the SetRequest.
-    repeated UpdateResult response = 2;
-    Error message = 3 [deprecated=true]; // The overall status of the transaction.
-    int64 timestamp = 4;                 // Timestamp of transaction (ns since epoch).
-}
-
-// UpdateResult is used within the SetResponse message to communicate the
-// result of an operation specified within a SetRequest message.
-// Reference: gNMI Specification Section 3.4.2
-message UpdateResult {
-    // The operation that was associated with the Path specified.
-    enum Operation {
-        INVALID = 0;
-        DELETE = 1;           // The result relates to a delete of Path.
-        REPLACE = 2;          // The result relates to a replace of Path.
-        UPDATE = 3;           // The result relates to an update of Path.
-    }
-    // Deprecated timestamp for the UpdateResult, this field has been
-    // replaced by the timestamp within the SetResponse message, since
-    // all mutations effected by a set should be applied as a single
-    // transaction.
-    int64 timestamp = 1 [deprecated=true];
-    Path path = 2;                            // Path associated with the update.
-    Error message = 3 [deprecated=true];      // Status of the update operation.
-    Operation op = 4;                         // Update operation type.
-}
-
-// GetRequest is sent when a client initiates a Get RPC. It is used to specify
-// the set of data elements for which the target should return a snapshot of
-// data. The use_models field specifies the set of schema modules that are to
-// be used by the target - where use_models is not specified then the target
-// must use all schema models that it has.
-// Reference: gNMI Specification Section 3.3.1
-message GetRequest {
-    Path prefix = 1;                      // Prefix used for paths.
-    repeated Path path = 2;               // Paths requested by the client.
-    // Type of elements within the data tree.
-    enum DataType {
-        ALL = 0;                            // All data elements.
-        CONFIG = 1;                         // Config (rw) only elements.
-        STATE = 2;                          // State (ro) only elements.
-        // Data elements marked in the schema as operational. This refers to data
-        // elements whose value relates to the state of processes or interactions
-        // running on the device.
-        OPERATIONAL = 3;
-    }
-    DataType type = 3;                    // The type of data being requested.
-    Encoding encoding = 5;                // Encoding to be used.
-    repeated ModelData use_models = 6;    // The schema models to be used.
-}
-
-// GetResponse is used by the target to respond to a GetRequest from a client.
-// The set of Notifications corresponds to the data values that are requested
-// by the client in the GetRequest.
-// Reference: gNMI Specification Section 3.3.2
-message GetResponse {
-    repeated Notification notification = 1;   // Data values.
-    Error error = 2 [deprecated=true];       // Errors that occurred in the Get.
-}
-
-// CapabilityRequest is sent by the client in the Capabilities RPC to request
-// that the target reports its capabilities.
-// Reference: gNMI Specification Section 3.2.1
-message CapabilityRequest {
-}
-
-// CapabilityResponse is used by the target to report its capabilities to the
-// client within the Capabilities RPC.
-// Reference: gNMI Specification Section 3.2.2
-message CapabilityResponse {
-    repeated ModelData supported_models = 1;    // Supported schema models.
-    repeated Encoding supported_encodings = 2;  // Supported encodings.
-    string gNMI_version = 3;                    // Supported gNMI version.
-}
-
-// ModelData is used to describe a set of schema modules. It can be used in a
-// CapabilityResponse where a target reports the set of modules that it
-// supports, and within the SubscribeRequest and GetRequest messages to specify
-// the set of models from which data tree elements should be reported.
-// Reference: gNMI Specification Section 3.2.3
-message ModelData {
-    string name = 1;            // Name of the model.
-    string organization = 2;    // Organization publishing the model.
-    string version = 3;         // Semantic version of the model.
-}
diff --git a/tools/build/bazel/gnmi_BUILD b/tools/build/bazel/gnmi_BUILD
new file mode 100644
index 0000000..43cb693
--- /dev/null
+++ b/tools/build/bazel/gnmi_BUILD
@@ -0,0 +1,17 @@
+proto_library(
+    name = "gnmi_proto",
+    srcs = ["gnmi/gnmi.proto"],
+    deps = [
+        ":gnmi_ext_proto",
+        "@com_google_protobuf//:descriptor_proto",
+        "@com_google_protobuf//:any_proto",
+    ],
+    visibility = ["//visibility:public"],
+)
+
+
+proto_library(
+    name = "gnmi_ext_proto",
+    srcs = ["gnmi_ext/gnmi_ext.proto"],
+    visibility = ["//visibility:public"],
+)
diff --git a/tools/build/bazel/gnmi_workspace.bzl b/tools/build/bazel/gnmi_workspace.bzl
new file mode 100644
index 0000000..6b0d4db
--- /dev/null
+++ b/tools/build/bazel/gnmi_workspace.bzl
@@ -0,0 +1,16 @@
+load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
+
+# FIXME: Currently gNMI proto file uses incorrect path to import "gnmi_ext.proto"
+#        Temporary use patch from ONF before gNMI team fix it.
+
+GNMI_COMMIT = "onos"
+GNMI_SHA = "0c4d5f168cb142f8135171204dac3ff8840a147f51fa361079f42fa585bec2ce"
+
+def generate_gnmi():
+    http_archive(
+        name = "com_github_openconfig_gnmi",
+        urls = ["https://github.com/opennetworkinglab/gnmi/archive/%s.zip" % GNMI_COMMIT],
+        sha256 = GNMI_SHA,
+        strip_prefix = "gnmi-%s/proto" % GNMI_COMMIT,
+        build_file = "//tools/build/bazel:gnmi_BUILD",
+    )