func (this *HookSwitchInspector) Start() error {
	log.Debugf("Initializing Ethernet Inspector %#v", this)
	var err error

	if this.EnableTCPWatcher {
		this.tcpWatcher = tcpwatcher.New()
	}

	this.trans, err = transceiver.NewTransceiver(this.OrchestratorURL, this.EntityID)
	if err != nil {
		return err
	}
	this.trans.Start()

	zmqSocket, err := zmq.NewSocket(zmq.Pair)
	if err != nil {
		return err
	}
	zmqSocket.Bind(this.HookSwitchZMQAddr)
	defer zmqSocket.Close()
	this.zmqChannels = zmqSocket.Channels()
	for {
		select {
		case msgBytes := <-this.zmqChannels.In():
			meta, ethBytes, err := this.decodeZMQMessageBytes(msgBytes)
			if err != nil {
				log.Error(err)
				continue
			}
			eth, ip, tcp := parseEthernetBytes(ethBytes)
			// note: tcpwatcher is not thread-safe
			if this.EnableTCPWatcher && this.tcpWatcher.IsTCPRetrans(ip, tcp) {
				meta.Op = hookswitch.Drop
				err = this.sendZMQMessage(*meta, nil)
				if err != nil {
					log.Error(err)
				}
				continue
			}
			go func() {
				if err := this.onHookSwitchMessage(*meta, eth, ip, tcp); err != nil {
					log.Error(err)
				}
			}()
		case err := <-this.zmqChannels.Errors():
			return err
		}
	}
	// NOTREACHED
}
func (this *NFQInspector) Start() error {
	log.Debugf("Initializing Ethernet Inspector %#v", this)
	var err error

	if this.EnableTCPWatcher {
		this.tcpWatcher = tcpwatcher.New()
	}

	this.trans, err = transceiver.NewTransceiver(this.OrchestratorURL, this.EntityID)
	if err != nil {
		return err
	}
	this.trans.Start()

	nfq, err := netfilter.NewNFQueue(this.NFQNumber, 256, netfilter.NF_DEFAULT_PACKET_SIZE)
	if err != nil {
		return err
	}
	defer nfq.Close()
	nfpChan := nfq.GetPackets()
	for {
		nfp := <-nfpChan
		ip, tcp := this.decodeNFPacket(nfp)
		// note: tcpwatcher is not thread-safe
		if this.EnableTCPWatcher && this.tcpWatcher.IsTCPRetrans(ip, tcp) {
			nfp.SetVerdict(netfilter.NF_DROP)
			continue
		}
		go func() {
			if err := this.onPacket(nfp, ip, tcp); err != nil {
				log.Error(err)
			}
		}()
	}
	// NOTREACHED
}