예제 #1
0
파일: controller.go 프로젝트: postfix/ogo
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
		}
	}
}
예제 #2
0
파일: switch.go 프로젝트: 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
	}
}