Finish off a couple of things to get PIM to send HELLOs.

Also added packet request to PacketService to get punt flows installed in switches.

Change-Id: I7340d09a1cf2ec06fb33ac0c4fc14eb43e94f496
diff --git a/apps/pim/src/main/java/org/onosproject/pim/impl/PIMApplication.java b/apps/pim/src/main/java/org/onosproject/pim/impl/PIMApplication.java
index a286726..6aa935e 100644
--- a/apps/pim/src/main/java/org/onosproject/pim/impl/PIMApplication.java
+++ b/apps/pim/src/main/java/org/onosproject/pim/impl/PIMApplication.java
@@ -37,10 +37,12 @@
 import org.onosproject.net.mcast.MulticastRouteService;
 import org.onosproject.net.packet.InboundPacket;
 import org.onosproject.net.packet.PacketContext;
+import org.onosproject.net.packet.PacketPriority;
 import org.onosproject.net.packet.PacketProcessor;
 import org.onosproject.net.packet.PacketService;
 import org.slf4j.Logger;
 
+import java.util.Optional;
 import java.util.Set;
 
 import static org.slf4j.LoggerFactory.getLogger;
@@ -85,6 +87,8 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected PIMInterfaceService pimInterfaceManager;
 
+    private final PIMPacketProcessor processor = new PIMPacketProcessor();
+
     /**
      * Activate the PIM component.
      */
@@ -100,10 +104,11 @@
         selector.matchIPProtocol(IPv4.PROTOCOL_PIM);
 
         // Use the traffic selector to tell the packet service which packets we want.
-        // PIMPacketService is an inner class defined below
-        PIMPacketProcessor processor = new PIMPacketProcessor();
         packetService.addProcessor(processor, PacketProcessor.director(5));
 
+        packetService.requestPackets(selector.build(), PacketPriority.CONTROL,
+                appId, Optional.empty());
+
         // Register for notifications from the Network config & Interface services.
         // We'll use these services to represent "PIMInterfaces"
 
@@ -121,6 +126,8 @@
      */
     @Deactivate
     public void deactivate() {
+        packetService.removeProcessor(processor);
+
         log.info("Stopped");
     }
 
diff --git a/apps/pim/src/main/java/org/onosproject/pim/impl/PIMInterface.java b/apps/pim/src/main/java/org/onosproject/pim/impl/PIMInterface.java
index b6ba703..454c431 100644
--- a/apps/pim/src/main/java/org/onosproject/pim/impl/PIMInterface.java
+++ b/apps/pim/src/main/java/org/onosproject/pim/impl/PIMInterface.java
@@ -24,9 +24,14 @@
 import org.onlab.packet.pim.PIMHello;
 import org.onlab.packet.pim.PIMHelloOption;
 import org.onosproject.incubator.net.intf.Interface;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficTreatment;
 import org.onosproject.net.host.InterfaceIpAddress;
+import org.onosproject.net.packet.DefaultOutboundPacket;
+import org.onosproject.net.packet.PacketService;
 import org.slf4j.Logger;
 
+import java.nio.ByteBuffer;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
@@ -42,7 +47,10 @@
 
     private final Logger log = getLogger(getClass());
 
+    private final PacketService packetService;
+
     private Interface onosInterface;
+    private final TrafficTreatment outputTreatment;
 
     // Our hello opt holdtime
     private short holdtime = PIMHelloOption.DEFAULT_HOLDTIME;
@@ -67,8 +75,10 @@
      *
      * @param intf the ONOS Interface.
      */
-    public PIMInterface(Interface intf) {
+    public PIMInterface(Interface intf, PacketService packetService) {
         onosInterface = intf;
+        outputTreatment = createOutputTreatment();
+        this.packetService = packetService;
         IpAddress ourIp = getIpAddress();
         MacAddress mac = intf.mac();
 
@@ -82,6 +92,12 @@
         drIpaddress = ourIp;
     }
 
+    private TrafficTreatment createOutputTreatment() {
+        return DefaultTrafficTreatment.builder()
+                .setOutput(onosInterface.connectPoint().port())
+                .build();
+    }
+
     /**
      * Return the ONOS Interface.
      *
@@ -187,7 +203,10 @@
         // Now set the hello option payload
         pimPacket.setPIMPayload(hello);
 
-        // TODO: How to send the packet.?.
+        packetService.emit(new DefaultOutboundPacket(
+                onosInterface.connectPoint().deviceId(),
+                outputTreatment,
+                ByteBuffer.wrap(pimPacket.getEthernet().serialize())));
     }
 
     /**
diff --git a/apps/pim/src/main/java/org/onosproject/pim/impl/PIMInterfaceManager.java b/apps/pim/src/main/java/org/onosproject/pim/impl/PIMInterfaceManager.java
index 9ff39fb..711db6c 100644
--- a/apps/pim/src/main/java/org/onosproject/pim/impl/PIMInterfaceManager.java
+++ b/apps/pim/src/main/java/org/onosproject/pim/impl/PIMInterfaceManager.java
@@ -25,6 +25,7 @@
 import org.onosproject.incubator.net.intf.Interface;
 import org.onosproject.incubator.net.intf.InterfaceService;
 import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.packet.PacketService;
 import org.onosproject.net.provider.ProviderId;
 import org.slf4j.Logger;
 import java.util.Map;
@@ -62,6 +63,9 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected InterfaceService interfaceService;
 
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected PacketService packetService;
+
     // Store PIM Interfaces in a map key'd by ConnectPoint
     private final Map<ConnectPoint, PIMInterface> pimInterfaces = Maps.newConcurrentMap();
 
@@ -72,7 +76,7 @@
 
         // Create PIM Interfaces for each of the existing ONOS Interfaces.
         for (Interface intf : interfaceService.getInterfaces()) {
-            pimInterfaces.put(intf.connectPoint(), new PIMInterface(intf));
+            pimInterfaces.put(intf.connectPoint(), new PIMInterface(intf, packetService));
         }
 
         // Schedule the periodic hello sender.
@@ -107,7 +111,7 @@
 
         log.debug("Updating Interface for " + intf.connectPoint().toString());
         pimInterfaces.compute(cp, (k, v) -> (v == null) ?
-                new PIMInterface(intf) :
+                new PIMInterface(intf, packetService) :
                 v.setInterface(intf));
     }