Пример #1
0
func makePort(portNo uint32, port gopenflow.Port) ofp4.Port {
	var config uint32
	for _, conf := range port.GetConfig() {
		switch c := conf.(type) {
		case gopenflow.PortConfigPortDown:
			if bool(c) {
				config |= ofp4.OFPPC_PORT_DOWN
			}
		case gopenflow.PortConfigNoRecv:
			if bool(c) {
				config |= ofp4.OFPPC_NO_RECV
			}
		case gopenflow.PortConfigNoFwd:
			if bool(c) {
				config |= ofp4.OFPPC_NO_FWD
			}
		case gopenflow.PortConfigNoPacketIn:
			if bool(c) {
				config |= ofp4.OFPPC_NO_PACKET_IN
			}
		}
	}

	var state uint32
	for _, st := range port.State() {
		switch s := st.(type) {
		case gopenflow.PortStateLinkDown:
			if bool(s) {
				state |= ofp4.OFPPS_LINK_DOWN
			}
		case gopenflow.PortStateBlocked:
			if bool(s) {
				state |= ofp4.OFPPS_BLOCKED
			}
		case gopenflow.PortStateLive:
			if bool(s) {
				state |= ofp4.OFPPS_LIVE
			}
		}
	}

	eth, err := port.Ethernet()
	if err != nil {
		log.Print(err)
	}
	return ofp4.MakePort(portNo,
		port.HwAddr(),
		[]byte(port.Name()),
		config,
		state,
		eth.Curr,
		eth.Advertised,
		eth.Supported,
		eth.Peer,
		eth.CurrSpeed,
		eth.MaxSpeed)
}
Пример #2
0
// SetPort sets a port in a specified portNo. To unset the port, pass nil as port argument.
func (self *Pipeline) AddPort(port gopenflow.Port) error {
	self.lock.Lock()
	defer self.lock.Unlock()

	portNo := uint32(1)
	for idx, p := range self.ports {
		if p == port {
			return fmt.Errorf("port already registered")
		}
		if idx >= portNo {
			portNo = idx + 1
		}
	}
	if portNo > ofp4.OFPP_MAX {
		return fmt.Errorf("no port number available")
		// we may reuse the port number
	}
	self.ports[portNo] = port
	self.portAlive[portNo] = watchTimer{}
	updateTimer := func(ofpPort []byte) {
		wt := self.portAlive[portNo]
		if ofp4.Port(ofpPort).State()&ofp4.OFPPS_LIVE != 0 {
			if wt.Active == nil {
				save := time.Now()
				wt.Active = &save
				self.portAlive[portNo] = wt
			}
		} else {
			if wt.Active != nil {
				wt.Past += time.Now().Sub(*wt.Active)
				wt.Active = nil
				self.portAlive[portNo] = wt
			}
		}
	}

	// add port first.
	ofpPort := makePort(portNo, port)
	self.portSnapshot[portNo] = ofpPort
	updateTimer(ofpPort)
	for _, ch := range self.channels {
		ch.Notify(ofp4.MakePortStatus(ofp4.OFPPR_ADD, ofpPort))
	}

	pktIngress := make(chan bool)
	go func() {
		for pkt := range port.Ingress() {
			oob := match(make(map[OxmKey]OxmPayload))
			if err := oob.UnmarshalBinary(pkt.Oob); err != nil {
				log.Print(err)
			} else {
				self.datapath <- &flowTask{
					Frame: Frame{
						serialized: pkt.Data,
						inPort:     portNo,
						inPhyPort:  port.PhysicalPort(),
						Oob:        oob,
					},
					pipe: self,
				}
			}
		}
		pktIngress <- true
	}()
	go func() {
		for _ = range port.Monitor() {
			ofpPort := makePort(portNo, port)
			if bytes.Equal(ofpPort, self.portSnapshot[portNo]) {
				continue
			} else {
				self.portSnapshot[portNo] = ofpPort
			}
			for _, ch := range self.channels {
				ch.Notify(ofp4.MakePortStatus(ofp4.OFPPR_MODIFY, ofpPort))
			}
			updateTimer(ofpPort)
		}
		for _, ch := range self.channels {
			ch.Notify(ofp4.MakePortStatus(ofp4.OFPPR_DELETE, self.portSnapshot[portNo]))
		}
		<-pktIngress
		delete(self.ports, portNo)
		delete(self.portSnapshot, portNo)
		delete(self.portAlive, portNo)
	}()
	return nil
}