Beispiel #1
0
Datei: core.go Projekt: 3d0c/ogo
func (o *OgoInstance) linkDiscoveryLoop(dpid net.HardwareAddr) {
	for {
		select {
		case <-o.shutdown:
			return
		// Every two seconds send a link discovery packet.
		case <-time.After(time.Second * 2):
			e := eth.New()
			e.Ethertype = 0xa0f1
			e.HWSrc = dpid[2:]
			linkDsc := NewLinkDiscovery()
			linkDsc.SrcDPID = dpid
			e.Data = linkDsc

			pkt := ofp10.NewPacketOut()
			pkt.Data = e
			pkt.AddAction(ofp10.NewActionOutput(ofp10.P_ALL))

			if sw, ok := Switch(dpid); ok {
				sw.Send(pkt)
			}
		}
	}
}
Beispiel #2
0
func (this *L3Forwarder) PacketIn(dpid net.HardwareAddr, pkt *ofp10.PacketIn) {
	ethFrame := pkt.Data
	ip := &ipv4.IPv4{}

	// Ignore link discovery packet types.
	if ethFrame.Ethertype == 0xa0f1 || ethFrame.Ethertype == 0x88cc {
		return
	}

	if _, found := this.arpTable.Dpid(dpid); !found {
		for _, fake := range this.fakeways {
			this.arpTable.Add(dpid, net.ParseIP(fake), host{dpidToMac(dpid), ofp10.P_NONE})
		}
	}

	if ethFrame.Ethertype == eth.IPv4_MSG {
		ip = ethFrame.Data.(*ipv4.IPv4)

		this.arpTable.Add(dpid, ip.NWSrc, host{ethFrame.HWSrc, pkt.InPort})

		log.Println(dpid, pkt.InPort, "IP", ip.NWSrc, "->", ip.NWDst)

		sendLostBuffers(dpid, ip.NWSrc, ethFrame.HWSrc, pkt.InPort)

		dstaddr := ip.NWDst

		if host, found := this.arpTable.Host(dpid, dstaddr); found {
			if host.port == pkt.InPort {
				log.Println(dpid, pkt.InPort, "not sending packet for", dstaddr.String(), "back out of the input port")
			} else {
				log.Println(dpid, pkt.InPort, "installing flow for", ip.NWSrc, "=>", ip.NWDst, "out port", host.port)
			}

			msg := ofp10.NewFlowMod()
			msg.Match.InPort = pkt.InPort

			msg.Match.DLDst = ethFrame.HWDst
			msg.Match.DLSrc = ethFrame.HWSrc

			msg.Match.Wildcards = ofp10.FW_ALL ^ ofp10.FW_DL_SRC ^ ofp10.FW_DL_DST
			msg.Command = ofp10.FC_ADD

			msg.AddAction(ofp10.NewActionDLDst(host.mac))
			msg.AddAction(ofp10.NewActionOutput(host.port))

			msg.IdleTimeout = 30
			msg.HardTimeout = 20
			msg.BufferId = pkt.BufferId

			if sw, ok := ogo.Switch(dpid); ok {
				sw.Send(msg)
			}

		} else {
			if _, found := lostBuffers[pair{dpid.String(), ip.NWDst.String()}]; !found {
				lostBuffers[pair{dpid.String(), ip.NWDst.String()}] = make([]buffer, 0)
			}

			lostBuffers[pair{dpid.String(), ip.NWDst.String()}] = append(lostBuffers[pair{dpid.String(), ip.NWDst.String()}], buffer{pkt.BufferId, pkt.InPort})

			arpReq, err := arp.New(arp.Type_Request)
			if err != nil {
				panic(err)
			}
			arpReq.HWDst, _ = net.ParseMAC("ff:ff:ff:ff:ff:ff")
			arpReq.IPDst = ip.NWDst
			arpReq.HWSrc = ethFrame.HWSrc
			arpReq.IPSrc = ip.NWSrc

			e := eth.New()
			e.Ethertype = eth.ARP_MSG
			e.HWSrc = ethFrame.HWSrc
			e.HWDst, _ = net.ParseMAC("ff:ff:ff:ff:ff:ff")
			e.Data = arpReq

			log.Println(dpid, pkt.InPort, "ARPing for", arpReq.IPDst, "on behalf of", arpReq.IPSrc)

			msg := ofp10.NewPacketOut()
			msg.InPort = pkt.InPort
			msg.Data = e
			msg.AddAction(ofp10.NewActionOutput(ofp10.P_FLOOD))

			if sw, ok := ogo.Switch(dpid); ok {
				sw.Send(msg)
			}
		}
	} else if ethFrame.Ethertype == eth.ARP_MSG {
		a := ethFrame.Data.(*arp.ARP)

		log.Println(dpid, pkt.InPort, "ARP", a.Operation, a.IPSrc, "->", a.IPDst)

		if _, found := this.arpTable.Host(dpid, a.IPSrc); found {
			log.Println("RE-learned:", dpid, pkt.InPort, a.IPSrc)
		} else {
			log.Println("learned:", dpid, pkt.InPort, a.IPSrc)
		}

		this.arpTable.Add(dpid, a.IPSrc, host{ethFrame.HWSrc, pkt.InPort})

		sendLostBuffers(dpid, a.IPSrc, ethFrame.HWSrc, pkt.InPort)

		if a.Operation == arp.Type_Request {
			if host, found := this.arpTable.Host(dpid, a.IPDst); found {
				arpReply, err := arp.New(arp.Type_Reply)
				if err != nil {
					panic(err)
				}

				arpReply.HWType = a.HWType
				arpReply.ProtoType = a.ProtoType
				arpReply.HWLength = a.HWLength
				arpReply.ProtoLength = a.ProtoLength
				arpReply.HWDst = a.HWSrc
				arpReply.IPDst = a.IPSrc
				arpReply.IPSrc = a.IPDst
				arpReply.HWSrc = host.mac

				e := eth.New()
				e.Ethertype = ethFrame.Ethertype
				e.HWSrc = dpidToMac(dpid)
				e.HWDst = a.HWSrc
				e.Data = arpReply

				log.Println(dpid, pkt.InPort, "answering ARP for", arpReply.IPSrc)

				msg := ofp10.NewPacketOut()
				msg.InPort = pkt.InPort
				msg.Data = e
				msg.AddAction(ofp10.NewActionOutput(ofp10.P_IN_PORT))

				if sw, ok := ogo.Switch(dpid); ok {
					sw.Send(msg)
				}

				return
			}
		}

		log.Println(dpid, pkt.InPort, "Flooding ARP", a.IPSrc, "->", a.IPDst)

		msg := ofp10.NewPacketOut()
		msg.InPort = pkt.InPort
		msg.Data = &ethFrame
		msg.AddAction(ofp10.NewActionOutput(ofp10.P_FLOOD))

		if sw, ok := ogo.Switch(dpid); ok {
			sw.Send(msg)
		}
	}
}