Example #1
0
func (c *Controller) handleConnection(conn *net.TCPConn) {
	stream := NewMessageStream(conn)
	stream.Outbound <- ofp10.NewHello()

	for {
		select {
		//case stream.Outbound <- ofp10.NewHello():
		// Send hello message with latest protocol version.
		case msg := <-stream.Inbound:
			switch m := msg.(type) {
			// A Hello message of the appropriate type
			// completes version negotiation. If version
			// types are incompatable, it is possible the
			// connection may be servered without error.
			case *ofp10.Header:
				if m.Version == ofp10.VERSION {
					// Version negotiation is
					// considered complete. Create
					// new Switch and notifiy listening
					// applications.
					stream.Version = m.Version
					stream.Outbound <- ofp10.NewFeaturesRequest()
				} else {
					// Connection should be severed if controller
					// doesn't support switch version.
					stream.Shutdown <- true
				}
			// After a vaild FeaturesReply has been received we
			// have all the information we need. Create a new
			// switch object and notify applications.
			case *ofp10.SwitchFeatures:
				NewSwitch(stream, *m)
				for _, newInstance := range Applications {
					if sw, ok := Switch(m.DPID); ok {
						i := newInstance()
						sw.AddInstance(i)
					}
				}
				return
			// An error message may indicate a version mismatch. We
			// disconnect if an error occurs this early.
			case *ofp10.ErrorMsg:
				log.Println(m)
				stream.Version = m.Header.Version
				stream.Shutdown <- true
			}
		case err := <-stream.Error:
			// The connection has been shutdown.
			log.Println(err)
			return
		case <-time.After(time.Second * 3):
			// This shouldn't happen. If it does, both the controller
			// and switch are no longer communicating. The TCPConn is
			// still established though.
			log.Println("Connection timed out.")
			return
		}
	}
}
Example #2
0
File: switch.go Project: jessta/ogo
/* Builds and populates Switch struct then starts listening
for OpenFlow messages on conn. */
func NewOpenFlowSwitch(conn *net.TCPConn) {

	if _, err := conn.ReadFrom(ofp10.NewHello()); err != nil {
		log.Println("ERROR::Switch.SendSync::ReadFrom:", err)
		conn.Close()
	}
	buf := make([]byte, 1500)
	n, _ := conn.Read(buf)
	res := ofp10.NewHello()
	res.Write(buf[:n])

	if _, err := conn.ReadFrom(ofp10.NewFeaturesRequest()); err != nil {
		log.Println("ERROR::Switch.SendSync::ReadFrom:", err)
		conn.Close()
	}
	buf2 := make([]byte, 1500)
	fres := ofp10.NewFeaturesReply()
	n, _ = conn.Read(buf2)
	fres.Write(buf2[:n])

	if sw, ok := Switches[fres.DPID.String()]; ok {
		log.Println("Recovered connection from:", sw.DPID)
		sw.conn = *conn
		go sw.SendSync()
		go sw.Receive()
	} else {
		log.Printf("Openflow 1.%d Connection: %s", res.Version-1, fres.DPID.String())
		s := new(Switch)
		s.conn = *conn
		s.DPID = fres.DPID
		s.Ports = make(map[int]ofp10.OfpPhyPort)
		s.requests = make(map[uint32]chan ofp10.OfpMsg)
		for _, p := range fres.Ports {
			s.Ports[int(p.PortNo)] = p
		}
		go s.SendSync()
		go s.Receive()
		Switches[s.DPID.String()] = s
	}
}
Example #3
0
File: core.go Project: postfix/ogo
func (o *OgoInstance) ConnectionUp(dpid net.HardwareAddr) {
	dropMod := ofp10.NewFlowMod()
	dropMod.Priority = 1

	arpFmod := ofp10.NewFlowMod()
	arpFmod.Priority = 2
	arpFmod.Match.DLType = 0x0806 // ARP Messages
	arpFmod.AddAction(ofp10.NewActionOutput(ofp10.P_CONTROLLER))

	dscFmod := ofp10.NewFlowMod()
	dscFmod.Priority = 0xffff
	dscFmod.Match.DLType = 0xa0f1 // Link Discovery Messages
	dscFmod.AddAction(ofp10.NewActionOutput(ofp10.P_CONTROLLER))

	if sw, ok := Switch(dpid); ok {
		sw.Send(ofp10.NewFeaturesRequest())
		sw.Send(dropMod)
		sw.Send(arpFmod)
		sw.Send(dscFmod)
		sw.Send(ofp10.NewEchoRequest())
	}
	go o.linkDiscoveryLoop(dpid)
}