Пример #1
0
// Pack Service to a set of nlattrs.
// If full is given, include service settings, otherwise only the identifying fields are given.
func (self *Service) attrs(full bool) nlgo.AttrSlice {
	var attrs nlgo.AttrSlice

	if self.FwMark != 0 {
		attrs = append(attrs,
			nlattr(IPVS_SVC_ATTR_AF, nlgo.U16(self.Af)),
			nlattr(IPVS_SVC_ATTR_FWMARK, nlgo.U32(self.FwMark)),
		)
	} else if self.Protocol != 0 && self.Addr != nil && self.Port != 0 {
		attrs = append(attrs,
			nlattr(IPVS_SVC_ATTR_AF, nlgo.U16(self.Af)),
			nlattr(IPVS_SVC_ATTR_PROTOCOL, nlgo.U16(self.Protocol)),
			nlattr(IPVS_SVC_ATTR_ADDR, packAddr(self.Af, self.Addr)),
			nlattr(IPVS_SVC_ATTR_PORT, packPort(self.Port)),
		)
	} else {
		panic("Incomplete service id fields")
	}

	if full {
		attrs = append(attrs,
			nlattr(IPVS_SVC_ATTR_SCHED_NAME, nlgo.NulString(self.SchedName)),
			nlattr(IPVS_SVC_ATTR_FLAGS, pack(&self.Flags)),
			nlattr(IPVS_SVC_ATTR_TIMEOUT, nlgo.U32(self.Timeout)),
			nlattr(IPVS_SVC_ATTR_NETMASK, nlgo.U32(self.Netmask)),
		)
	}

	return attrs
}
Пример #2
0
func TestInfo(t *testing.T) {
	testAttrs := nlgo.AttrMap{Policy: ipvs_info_policy, AttrSlice: nlgo.AttrSlice{
		{Header: syscall.NlAttr{Type: IPVS_INFO_ATTR_VERSION}, Value: nlgo.U32(0x00010203)},
		{Header: syscall.NlAttr{Type: IPVS_INFO_ATTR_CONN_TAB_SIZE}, Value: nlgo.U32(4096)},
	}}

	if info, err := unpackInfo(testAttrs); err != nil {
		t.Errorf("error Info.unpack(): %s", err)
	} else {
		if info.Version.String() != "1.2.3" {
			t.Errorf("fail Info.Version: %s != 1.2.3", info.Version.String())
		}

		if info.ConnTabSize != 4096 {
			t.Errorf("fail Info.ConnTabSize: %s != 4096", info.ConnTabSize)
		}
	}
}
Пример #3
0
// Dump Dest as nl attrs, using the Af of the corresponding Service.
// If full, includes Dest setting attrs, otherwise only identifying attrs.
func (self *Dest) attrs(service *Service, full bool) nlgo.AttrSlice {
	var attrs nlgo.AttrSlice

	attrs = append(attrs,
		nlattr(IPVS_DEST_ATTR_ADDR, packAddr(service.Af, self.Addr)),
		nlattr(IPVS_DEST_ATTR_PORT, packPort(self.Port)),
	)

	if full {
		attrs = append(attrs,
			nlattr(IPVS_DEST_ATTR_FWD_METHOD, nlgo.U32(self.FwdMethod)),
			nlattr(IPVS_DEST_ATTR_WEIGHT, nlgo.U32(self.Weight)),
			nlattr(IPVS_DEST_ATTR_U_THRESH, nlgo.U32(self.UThresh)),
			nlattr(IPVS_DEST_ATTR_L_THRESH, nlgo.U32(self.LThresh)),
		)
	}

	return attrs
}
Пример #4
0
func TestDest(t *testing.T) {
	testService := Service{
		Af: syscall.AF_INET6,
	}
	testDest := Dest{
		Addr: net.ParseIP("2001:db8:6b:6b::0"),
		Port: 1337,

		FwdMethod: IP_VS_CONN_F_TUNNEL,
		Weight:    10,
		UThresh:   1000,
		LThresh:   0,
	}
	testAttrs := nlgo.AttrSlice{
		nlattr(IPVS_DEST_ATTR_ADDR, nlgo.Binary([]byte{0x20, 0x01, 0x0d, 0xb8, 0x00, 0x6b, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})),
		nlattr(IPVS_DEST_ATTR_PORT, nlgo.U16(0x3905)),
		nlattr(IPVS_DEST_ATTR_FWD_METHOD, nlgo.U32(IP_VS_CONN_F_TUNNEL)),
		nlattr(IPVS_DEST_ATTR_WEIGHT, nlgo.U32(10)),
		nlattr(IPVS_DEST_ATTR_U_THRESH, nlgo.U32(1000)),
		nlattr(IPVS_DEST_ATTR_L_THRESH, nlgo.U32(0)),
	}

	// pack
	packAttrs := testDest.attrs(&testService, true)
	packBytes := packAttrs.Bytes()

	if !bytes.Equal(packBytes, testAttrs.Bytes()) {
		t.Errorf("fail Dest.attrs(): \n%s", hex.Dump(packBytes))
	}

	// unpack
	if unpackedAttrs, err := ipvs_dest_policy.Parse(packBytes); err != nil {
		t.Fatalf("error ipvs_dest_policy.Parse: %s", err)
	} else if unpackedDest, err := unpackDest(testService, unpackedAttrs.(nlgo.AttrMap)); err != nil {
		t.Fatalf("error unpackDest: %s", err)
	} else {
		testDestEquals(t, testDest, unpackedDest)
	}
}
Пример #5
0
func (self *NamedPortManager) RtListen(ev nlgo.RtMessage) {
	mtype := ev.Message.Header.Type
	if mtype != syscall.RTM_NEWLINK && mtype != syscall.RTM_DELLINK {
		return // no concern
	}

	ifinfo := (*syscall.IfInfomsg)(unsafe.Pointer(&ev.Message.Data[0]))
	evPort := &NamedPort{
		ifIndex: uint32(ifinfo.Index),
		flags:   ifinfo.Flags,
		fd:      -1,
		lock:    &sync.Mutex{},
		rhub:    self.rhub,
	}
	if attrs, err := nlgo.RouteLinkPolicy.Parse(ev.Message.Data[nlgo.NLMSG_ALIGN(syscall.SizeofIfInfomsg):]); err != nil {
		log.Print(err)
	} else if amap, ok := attrs.(nlgo.AttrMap); !ok {
		log.Print("route link policy did not return attr map")
	} else {
		if t := amap.Get(nlgo.IFLA_IFNAME); t != nil {
			evPort.name = string(t.(nlgo.NulString))
		}
		if t := amap.Get(nlgo.IFLA_MTU); t != nil {
			evPort.mtu = uint32(t.(nlgo.U32))
		}
		if t := amap.Get(nlgo.IFLA_ADDRESS); t != nil {
			evPort.mac = []byte(t.(nlgo.Binary))
		}
	}

	switch mtype {
	case syscall.RTM_NEWLINK:
		if port := self.ports[evPort.ifIndex]; port != nil {
			port.flags = ifinfo.Flags
			if len(evPort.name) > 0 {
				port.name = evPort.name
			}
			if evPort.mtu != 0 {
				port.mtu = evPort.mtu
			}
			if len(evPort.mac) != 0 {
				port.mac = evPort.mac
			}
			port.monitor <- true
			if err := port.Up(); err != nil { // maybe ready for up
				log.Print(err)
			}
			return
		}
		// query wiphy
		if res, err := self.ghub.Request("nl80211", 1, nlgo.NL80211_CMD_GET_INTERFACE, syscall.NLM_F_DUMP, nil, nlgo.AttrSlice{
			nlgo.Attr{
				Header: syscall.NlAttr{
					Type: nlgo.NL80211_ATTR_IFINDEX,
				},
				Value: nlgo.U32(ifinfo.Index),
			},
		}); err != nil {
			log.Print(err)
		} else {
			for _, r := range res {
				if r.Error != nil {
					log.Print(r.Error)
				}
				if r.Family != "nl80211" {
					continue
				}
				if attrs, err := nlgo.Nl80211Policy.Parse(r.Payload); err != nil {
					log.Print(err)
				} else if amap, ok := attrs.(nlgo.AttrMap); !ok {
					log.Print("nl80211 attr policy error")
				} else {
					if evPort.ifIndex == uint32(amap.Get(nlgo.NL80211_ATTR_IFINDEX).(nlgo.U32)) {
						evPort.hasWiphy = true
						evPort.wiphy = uint32(amap.Get(nlgo.NL80211_ATTR_WIPHY).(nlgo.U32))
					}
				}
			}
		}
		tracking := func(port *NamedPort) bool {
			for _, name := range self.trackingNames {
				if port.name == name {
					return true
				}
			}
			if port.hasWiphy {
				for _, wiphy := range self.trackingWiphy {
					if port.wiphy == wiphy {
						return true
					}
				}
			}
			for idx, _ := range self.ports {
				if idx == port.ifIndex {
					return true
				}
			}
			return false
		}
		if tracking(evPort) {
			port := evPort
			port.ingress = make(chan Frame)
			port.monitor = make(chan bool)
			self.ports[uint32(ifinfo.Index)] = port
			func() {
				if port.hasWiphy {
					for _, wiphy := range self.trackingWiphy {
						if wiphy == port.wiphy {
							return
						}
					}
					self.trackingWiphy = append(self.trackingWiphy, port.wiphy)
				}
			}()
			self.datapath.AddPort(port)
			port.monitor <- true
			if err := port.Up(); err != nil { // maybe ready for up
				log.Print(err)
			}
		}
	case syscall.RTM_DELLINK:
		if port, ok := self.ports[evPort.ifIndex]; ok && port != nil {
			port.Down()
			port.Close()
			delete(self.ports, evPort.ifIndex)
		}
		// for wiphy unplug
		if res, err := self.ghub.Request("nl80211", 1, nlgo.NL80211_CMD_GET_WIPHY, syscall.NLM_F_DUMP, nil, nil); err != nil {
			log.Print(err)
		} else {
			var activeWiphy []uint32
			for _, r := range res {
				if r.Family != "nl80211" {
					continue
				}
				if attrs, err := nlgo.Nl80211Policy.Parse(r.Payload); err != nil {
					log.Print(err)
				} else {
					activeWiphy = append(activeWiphy, uint32(attrs.(nlgo.AttrMap).Get(nlgo.NL80211_ATTR_WIPHY).(nlgo.U32)))
				}
			}
			var trackingWiphy []uint32
			for _, wiphy := range self.trackingWiphy {
				for _, active := range activeWiphy {
					if wiphy == active {
						trackingWiphy = append(trackingWiphy, wiphy)
					}
				}
			}
			self.trackingWiphy = trackingWiphy
		}
	}
}