Async/streaming gRPC client/server proto

This experiment was to fine-tune how we can implement
async gRPC client and server code inside a Twisted
python app.

Change-Id: I945014e27f4b9d6ed624666e0284cc298548adb3

Major cleanup of openflow_13.proto

Change-Id: I4e54eaf87b682124ec518a0ade1a6050a6ec6da8

Relocated openflow_13.proto to voltha

Change-Id: I66ae45a9142d180c2c6651e75c7a1ee08aef7ef8

Removed forced utest from make build

Change-Id: If0da58e9d135ebde6ca68c3316688a03a7b10f2f

twisted openflow agent first pass

Change-Id: Ibe5b4727ccfe92e6fd464ccd3baf6275569ef5d3

store openflow derived files

Change-Id: Ib3e1384bb2ca2a9c0872767f7b793f96b0a154e2

Minor cleanup

Change-Id: I1280ed3acb606121b616a0efd573f5f59d010dca

Factored out common utils

Change-Id: Icd86fcd50f60d0900924674cbcd65e13e47782a1

Refactored twisted agent

Change-Id: I71f26ce5357a4f98477df60b8c5ddc068cf75d43

Relocated openflow agent to ofagent

... and preserved obsolete working (non-twisted) agent under
~/obsolete, so we can still run the olt-oftest and pass tests,
unit the new twisted based agent reaches that maturity point.

Change-Id: I727f8d7144b1291a40276dad2966b7643bd7bc4b

olt-oftest in fake mode works with new agent

Change-Id: I43b4f5812e8dfaa9f45e4a77fdcf6c30ac520f8d

Initial ofagent/voltha operation

Change-Id: Ia8104f1285a6b1c51635d36d7d78fc113f800e79

Additional callouts to Voltha

Change-Id: If8f483d5140d3c9d45f22b480b8d33249a29cd4e

More gRPC calls

Change-Id: I7d24fadf9425217fb26ffe18f25359d072ef38fa

Flow add/list now works

Change-Id: Ie3e3e73108645b47891cef798fc61372a022fd93

Missed some files

Change-Id: I29e81238ff1a26c095c0c73e521579edf7092e21
diff --git a/obsolete/backends/mock.py b/obsolete/backends/mock.py
new file mode 100644
index 0000000..75c9c5a
--- /dev/null
+++ b/obsolete/backends/mock.py
@@ -0,0 +1,195 @@
+"""
+Mock backend for testing purposes
+"""
+
+import logging
+import os
+import sys
+from threading import Thread
+
+from hexdump import hexdump
+from scapy.all import Ether, IP, UDP, Dot1Q, sendp, sniff
+
+# VERY IMPORTANT:
+# Without the below hack, scapy will not properly receive VLAN
+# header (see http://stackoverflow.com/questions/18994242/why-isnt-scapy-capturing-vlan-tag-information).
+#
+from scapy.all import conf, ETH_P_ALL
+import pcap
+conf.use_pcap = True
+import scapy.arch.pcapdnet
+assert conf.L2listen.__name__=='L2pcapListenSocket'
+
+sys.path.insert(1, os.path.join(sys.path[0], '..'))
+
+import loxi.of13 as ofp
+from ofagent.utils import mac_str_to_tuple
+
+
+class MockBackend(object):
+
+    mfr_desc = "Ciena Corp."
+    hw_desc = "mock"
+
+    def __init__(self, store, in_out_iface=None, in_out_stag=None):
+        self.store = store
+        self.add_some_ports()
+        self.in_out_iface = in_out_iface
+        self.in_out_stag = in_out_stag
+        self.agent = None
+        self.in_out_receiver = None
+
+    def set_agent(self, agent):
+        self.agent = agent
+        if self.in_out_iface is not None:
+            self.in_out_receiver = InOutReceiver(self.in_out_iface, agent, self.in_out_stag)
+            self.in_out_receiver.start()
+
+    def stop(self):
+        if self.in_out_receiver is not None:
+            self.in_out_receiver.stop()
+
+    def get_serial_num(self):
+        return "DFG-4567-RTYU-789"
+
+    def get_dp_desc(self):
+        return "mock device"
+
+    def add_some_ports(self):
+        cap = ofp.OFPPF_1GB_FD | ofp.OFPPF_FIBER
+        for pno, mac, nam, cur, adv, sup, spe in (
+                (  1, '00:00:00:00:00:01', 'onu1', cap, cap, cap, ofp.OFPPF_1GB_FD),
+                (  2, '00:00:00:00:00:02', 'onu2', cap, cap, cap, ofp.OFPPF_1GB_FD),
+                (129, '00:00:00:00:00:81', 'olt',  cap, cap, cap, ofp.OFPPF_1GB_FD)
+            ):
+            port = ofp.common.port_desc(pno, mac_str_to_tuple(mac), nam,
+                                        curr=cur, advertised=adv, supported=sup,
+                                        curr_speed=spe, max_speed=spe)
+            self.store.port_add(port)
+
+    def packet_out(self, in_port, out_port, data):
+        in_port = "CONTROLLER" if in_port == ofp.OFPP_CONTROLLER else in_port
+        print "PACKET OUT (%s => %s): " % (in_port, out_port)
+        hexdump(data)
+
+        if self.in_out_iface is not None:
+
+            try:
+                # disect the packet
+                pkt = Ether(data)
+
+                # remove payload from Ether frame
+                payload = pkt.payload
+                payload_type = pkt.type
+                pkt.remove_payload()
+
+                # insert Dot1Q shim with vlan_id = out_port
+
+                if self.in_out_stag is None:
+                    ## WARNING -- This was changed from 0x88a8 to 0x8100 when
+                    ## testing with the Intel XL710 quad 10GE boards.  The
+                    ## XL710 does not support the TPID for the STAG.
+                    ##
+                    ## Long term, it should be changed back to 0x88a8!
+                    ##
+                    pkt.type = 0x8100
+                    new_pkt = pkt / Dot1Q(vlan=out_port, type=payload_type) / payload
+
+                else:
+                    pkt.type = 0x8100
+                    new_pkt = (
+                            pkt /
+                            Dot1Q(vlan=self.in_out_stag, type=0x8100) /
+                            Dot1Q(vlan=out_port, type=payload_type) /
+                            payload)
+
+                # send out the packet
+                sendp(new_pkt, iface=self.in_out_iface)
+
+            except Exception, e:
+                logging.exception("Could not parse packet-out data as scapy.Ether:\n")
+                logging.error(hexdump(data, 'return'))
+
+
+class InOutReceiver(Thread):
+
+    def __init__(self, iface, agent, in_out_stag=None):
+        Thread.__init__(self)
+        self.iface = iface
+        self.finished = False
+        self.agent = agent
+        self.in_out_stag = in_out_stag
+
+    def run(self):
+        # TODO this loop could be reconciled with the ofp Connection to become a
+        # single select loop.
+        self.sock = s = conf.L2listen(
+            type=ETH_P_ALL,
+            iface=self.iface,
+            filter='inbound'
+        )
+        while not self.finished:
+            try:
+                sniffed = sniff(1, iface=self.iface, timeout=1, opened_socket=s)
+                print 'Sniffer received %d packet(s)' % len(sniffed)
+                for pkt in sniffed:
+                    self.forward_packet(pkt)
+
+            except Exception, e:
+                logging.error("scapy.sniff error: %s" % e)
+
+    def stop(self):
+        """
+        Signal the thread to exit and wait for it
+        """
+        assert not self.finished
+        logging.debug("Stop sniffing on in-out channel")
+        self.finished = True
+        self.sock.close()
+        self.join()
+
+    def forward_packet(self, pkt):
+        print "Received packet:"
+        hexdump(str(pkt))
+        pkt.show()
+
+        try:
+            assert isinstance(pkt, Ether)
+            assert isinstance(pkt.getlayer(1), Dot1Q)
+            dot1q = pkt.getlayer(1)
+            assert isinstance(dot1q, Dot1Q)
+
+            if self.in_out_stag is None:
+                payload = dot1q.payload
+                payload_type = dot1q.type
+                pkt.remove_payload()
+
+                pkt.type = payload_type
+                new_pkt = pkt / payload
+                in_port = dot1q.vlan
+
+            else:
+                if dot1q.vlan != self.in_out_stag:
+                    print 'Dropping packet because outer tag %d does not match %d' % (
+                        dot1q.vlan, self.in_out_stag)
+                    return
+                dot1q_inner = dot1q.getlayer(1)
+                assert isinstance(dot1q_inner, Dot1Q)
+                payload = dot1q_inner.payload
+                payload_type = dot1q_inner.type
+                pkt.remove_payload()
+
+                pkt.type = payload_type
+                new_pkt = pkt / payload
+                in_port = dot1q_inner.vlan
+
+            if self.agent is not None:
+                self.agent.send_packet_in(str(new_pkt), in_port=in_port)
+                print 'new packet forwarded to controller (with in_port=%d):' % in_port
+                new_pkt.show()
+
+        except Exception, e:
+            logging.exception("Unexpected packet format received by InOutReceiver: %s" % e)
+            logging.error(hexdump(str(pkt), 'return'))
+
+