예제 #1
0
파일: application.go 프로젝트: 3d0c/ogo
func (b *DemoInstance) PacketIn(dpid net.HardwareAddr, pkt *ofp10.PacketIn) {
	eth := pkt.Data
	// Ignore link discovery packet types.
	if eth.Ethertype == 0xa0f1 || eth.Ethertype == 0x88cc {
		return
	}

	b.SetHost(eth.HWSrc, pkt.InPort)
	if host, ok := b.Host(eth.HWDst); ok {
		f1 := ofp10.NewFlowMod()
		f1.Match.DLSrc = eth.HWSrc
		f1.Match.DLDst = eth.HWDst
		f1.AddAction(ofp10.NewActionOutput(host.port))
		f1.IdleTimeout = 3

		f2 := ofp10.NewFlowMod()
		f2.Match.DLSrc = eth.HWDst
		f2.Match.DLDst = eth.HWSrc
		f2.AddAction(ofp10.NewActionOutput(pkt.InPort))
		f2.IdleTimeout = 3

		if s, ok := ogo.Switch(dpid); ok {
			s.Send(f1)
			s.Send(f2)
		}
	} else {
		p := ofp10.NewPacketOut()
		p.InPort = pkt.InPort
		p.AddAction(ofp10.NewActionOutput(ofp10.P_ALL))
		p.Data = &eth
		if sw, ok := ogo.Switch(dpid); ok {
			sw.Send(p)
		}
	}
}
예제 #2
0
func (this *L2Forwarder) PacketIn(dpid net.HardwareAddr, pkt *ofp10.PacketIn) {
	eth := pkt.Data

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

	// this.SetHost(eth.HWSrc, pkt.InPort)
	this.hostmap.Add(eth.HWSrc, pkt.InPort)

	if host, ok := this.hostmap.Host(eth.HWDst); ok {
		if host.port == pkt.InPort {
			log.Println("Same port for packet from %s -> %s on %s.%s\n", eth.HWSrc, eth.HWDst, dpid, host.port)
			return
		}

		f1 := ofp10.NewFlowMod()

		f1.Match.DLSrc = eth.HWSrc
		f1.Match.DLDst = eth.HWDst
		f1.Match.InPort = pkt.InPort
		f1.Flags = ofp10.FC_ADD
		f1.Match.Wildcards = ofp10.FW_ALL ^ ofp10.FW_DL_SRC ^ ofp10.FW_DL_DST

		f1.AddAction(ofp10.NewActionOutput(host.port))
		f1.IdleTimeout = 10

		f2 := ofp10.NewFlowMod()
		f2.Match.DLSrc = eth.HWDst
		f2.Match.DLDst = eth.HWSrc
		f2.Match.InPort = host.port
		f2.AddAction(ofp10.NewActionOutput(pkt.InPort))
		f2.IdleTimeout = 3

		log.Println("Installing flow for", eth.HWSrc, pkt.InPort, "<-->", eth.HWDst, host.port)
		log.Println("Installing flow for", eth.HWDst, host.port, "<-->", eth.HWSrc, pkt.InPort)

		if s, ok := ogo.Switch(dpid); ok {
			s.Send(f1)
			s.Send(f2)
		}
	} else {
		p := ofp10.NewPacketOut()
		p.InPort = pkt.InPort
		p.BufferId = pkt.BufferId
		p.Data = &eth

		p.AddAction(ofp10.NewActionOutput(ofp10.P_FLOOD))

		if sw, ok := ogo.Switch(dpid); ok {
			sw.Send(p)
		}
	}
}
예제 #3
0
func sendLostBuffers(dpid net.HardwareAddr, ipaddr net.IP, macaddr net.HardwareAddr, port uint16) {
	if _, found := lostBuffers[pair{dpid.String(), ipaddr.String()}]; !found {
		return
	}

	buffers := lostBuffers[pair{dpid.String(), ipaddr.String()}]
	for _, buffer := range buffers {
		msg := ofp10.NewPacketOut()
		msg.InPort = buffer.inport
		msg.BufferId = buffer.bufferId
		msg.Data = nil
		msg.AddAction(ofp10.NewActionDLDst(macaddr))
		msg.AddAction(ofp10.NewActionOutput(port))
		if sw, ok := ogo.Switch(dpid); ok {
			sw.Send(msg)
		}
	}

	delete(lostBuffers, pair{dpid.String(), ipaddr.String()})
}
예제 #4
0
func TestMod(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	f1 := ofp10.NewFlowMod()

	f1.Match.DLSrc, _ = net.ParseMAC("22:11:11:22:22:22")
	f1.Match.DLDst, _ = net.ParseMAC("55:44:55:66:77:88")
	f1.Match.InPort = 5
	// f1.Flags = ofp10.FC_ADD
	// f1.Match.Wildcards = ofp10.FW_ALL ^ ofp10.FW_DL_SRC ^ ofp10.FW_DL_DST

	f1.AddAction(ofp10.NewActionOutput(1))

	dpid, err := net.ParseMAC(ps.ByName("dpid"))
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
	}

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

}
예제 #5
0
파일: core.go 프로젝트: 3d0c/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)
}
예제 #6
0
파일: core.go 프로젝트: 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)
			}
		}
	}
}
예제 #7
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)
		}
	}
}