Пример #1
0
func NewNetlinkMonitor(g canvas.Graph, r *Renderer, modules *bpf.BpfTable) (res *NetlinkMonitor, err error) {
	nlmon := &NetlinkMonitor{
		updates: make(chan netlink.LinkUpdate),
		done:    make(chan struct{}),
		flush:   make(chan struct{}),
		nodes:   make(map[int]*ExtInterface),
		g:       g,
		r:       r,
		modules: modules,
	}
	err = netlink.LinkSubscribe(nlmon.updates, nlmon.done)
	defer func() {
		if err != nil {
			nlmon.Close()
		}
	}()
	if err != nil {
		return
	}
	links, err := netlink.LinkList()
	if err != nil {
		return
	}
	for _, link := range links {
		nlmon.handleNewlink(link)
	}
	Debug.Println("NewNetlinkMonitor DONE")
	go nlmon.ParseLinkUpdates()
	res = nlmon
	return
}
Пример #2
0
// monitorPort watches for link flap events
func (vl *VlanBridge) monitorPort(ifname string) {
	vl.nlCloser = make(chan struct{})
	updChan := make(chan netlink.LinkUpdate)
	if err := netlink.LinkSubscribe(updChan, vl.nlCloser); err != nil {
		log.Errorf("Error listening on netlink: %v", err)
		return
	}

	go vl.handlePortUp(updChan, ifname)

}
Пример #3
0
func ensureInterface(ifaceName string) (*net.Interface, error) {
	if iface, err := findInterface(ifaceName); err == nil {
		return iface, nil
	}
	ch := make(chan netlink.LinkUpdate)
	done := make(chan struct{})
	defer close(done)
	if err := netlink.LinkSubscribe(ch, done); err != nil {
		return nil, err
	}
	for update := range ch {
		if ifaceName == update.Link.Attrs().Name && update.IfInfomsg.Flags&syscall.IFF_UP != 0 {
			break
		}
	}
	iface, err := findInterface(ifaceName)
	return iface, err
}
Пример #4
0
Файл: if.go Проект: n054/weave
func ensureInterface(ifaceName string) (*net.Interface, error) {
	ch := make(chan netlink.LinkUpdate)
	// NB: We do not supply (and eventually close) a 'done' channel
	// here since that can cause incorrect file descriptor
	// re-usage. See https://github.com/weaveworks/weave/issues/2120
	if err := netlink.LinkSubscribe(ch, nil); err != nil {
		return nil, err
	}
	// check for currently-existing interface after subscribing, to avoid race
	if iface, err := findInterface(ifaceName); err == nil {
		return iface, nil
	}
	for update := range ch {
		if ifaceName == update.Link.Attrs().Name && update.IfInfomsg.Flags&syscall.IFF_UP != 0 {
			break
		}
	}
	iface, err := findInterface(ifaceName)
	return iface, err
}
Пример #5
0
// This function should be put into the main process or somewhere that can be
// use to init the network namespace trap.
func setupNetworkNsTrap(netNs2Containerd func(supervisor.NetlinkUpdate)) {

	// Subscribe for links change event
	chLink := make(chan netlink.LinkUpdate)
	doneLink := make(chan struct{})
	defer close(doneLink)
	if err := netlink.LinkSubscribe(chLink, doneLink); err != nil {
		glog.Fatal(err)
	}

	// Subscribe for addresses change event
	chAddr := make(chan netlink.AddrUpdate)
	doneAddr := make(chan struct{})
	defer close(doneAddr)
	if err := netlink.AddrSubscribe(chAddr, doneAddr); err != nil {
		glog.Fatal(err)
	}

	// Subscribe for route change event
	chRoute := make(chan netlink.RouteUpdate)
	doneRoute := make(chan struct{})
	defer close(doneRoute)
	if err := netlink.RouteSubscribe(chRoute, doneRoute); err != nil {
		glog.Fatal(err)
	}

	for {
		select {
		case updateLink := <-chLink:
			handleLink(updateLink, netNs2Containerd)
		case updateAddr := <-chAddr:
			handleAddr(updateAddr, netNs2Containerd)
		case updateRoute := <-chRoute:
			handleRoute(updateRoute, netNs2Containerd)
		}
	}
}
Пример #6
0
func main() {
	var err error
	var buf []byte
	var data map[string]string

	if *flagVersion {
		fmt.Printf("%s build %s\n", Version, BuildTime)
		os.Exit(0)
	}

	if *flagInstall {
		if err = installService(); err != nil {
			log.Fatalf("failed to install service: %s\n", err.Error())
			os.Exit(1)
		}
		os.Exit(0)
	}

	l, err = syslog.Dial("", "", syslog.LOG_DAEMON|syslog.LOG_INFO, filepath.Base(os.Args[0]))
	if err != nil {
		log.Fatalf("Failed to connect to syslog: %s\n", err.Error())
		os.Exit(1)
	}
	defer l.Close()

	for _, fname := range []string{"svirtnet.yml", "cloudmeta.yaml"} {
		if buf, err = ioutil.ReadFile(filepath.Join("/etc", fname)); err == nil {
			if err = yaml.Unmarshal(buf, &data); err == nil {
				if val, ok := data["interface"]; ok && val != "" {
					master_iface = val
				}
				if val, ok := data["ipset_support"]; ok {
					if val == "false" {
						ipset_support = false
					}
				}
				if val, ok := data["xmlnsuri"]; ok && val != "" {
					xmlnsuri = val
				}
			}
		}
	}

	l.Info("ListenAndServeTCPv4")
	go ListenAndServeTCPv4()

	lnkupdate := make(chan netlink.LinkUpdate)
	lnkdone := make(chan struct{})
	err = netlink.LinkSubscribe(lnkupdate, lnkdone)
	if err != nil {
		l.Err(err.Error())
		os.Exit(1)
	}
	defer close(lnkdone)

	ifaces, err := net.Interfaces()
	if err != nil {
		l.Err(err.Error())
		os.Exit(1)
	}

	for _, iface := range ifaces {
		name := iface.Name
		l.Info("Check iface " + name)
		if !strings.HasPrefix(name, "tap") {
			continue
		}
		servers.Lock()
		if _, ok := servers.Get(name[3:]); !ok {
			s := &Server{name: name[3:]}
			servers.Add(name[3:], s)
			l.Info(name[3:] + " start serving")
			wait := make(chan struct{})
			go func() {
				defer func() {
					if r := recover(); r != nil {
						err, ok := r.(error)
						if !ok {
							err = fmt.Errorf("pkg: %v", r)
						}
						fmt.Printf(err.Error())
					}
				}()
				if err := s.Start(); err != nil {
					panic(err)
				}
				close(wait)
			}()
			<-wait
		}
		servers.Unlock()
	}

	sg := make(chan os.Signal, 1)
	signal.Notify(sg, unix.SIGINT, unix.SIGQUIT, unix.SIGTERM, unix.SIGHUP)

	tk := time.NewTicker(2 * time.Minute)
	defer tk.Stop()
	for {
		select {
		case <-tk.C:
			servers.Lock()
			for _, s := range servers.List() {
				t := time.Now().Add(5 * time.Minute)
				if !s.downtime.IsZero() && t.After(s.downtime) {
					servers.Del(s.name)
				}
			}
			servers.Unlock()
		case signame := <-sg:
			fmt.Println("Got signal:", signame)
			switch signame {
			case syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM:
				servers.Lock()
				for _, s := range servers.List() {
					wait := make(chan struct{})
					go func() {
						defer func() {
							if r := recover(); r != nil {
								err, ok := r.(error)
								if !ok {
									err = fmt.Errorf("pkg: %v", r)
								}
								fmt.Printf(err.Error())
							}
						}()
						if err := s.Stop(false); err != nil {
							panic(err)
						}
						close(wait)
					}()
					<-wait
					servers.Del(s.name)
				}
				servers.Unlock()
				os.Exit(0)
			}
		case msg := <-lnkupdate:
			if !strings.HasPrefix(msg.Attrs().Name, "tap") {
				continue
			}
			switch msg.Header.Type {
			case unix.RTM_NEWLINK:
				if msg.Change == unix.IFF_UP {
					//					fmt.Printf("newlink %#+v\n", msg)
					name := msg.Attrs().Name[3:]
					servers.Lock()
					if s, ok := servers.Get(name); !ok {
						s = &Server{name: name}
						servers.Add(name, s)
						go func() {
							defer func() {
								if r := recover(); r != nil {
									err, ok := r.(error)
									if !ok {
										err = fmt.Errorf("pkg: %v", r)
									}
									fmt.Printf(err.Error())
								}
							}()
							if err := s.Start(); err != nil {
								panic(err)
							}
						}()
					} else {
						go func() {
							defer func() {
								if r := recover(); r != nil {
									err, ok := r.(error)
									if !ok {
										err = fmt.Errorf("pkg: %v", r)
									}
									fmt.Printf(err.Error())
								}
							}()
							if err := s.Start(); err != nil {
								panic(err)
							}
						}()
					}
					servers.Unlock()
				}
			case unix.RTM_DELLINK:
				//				if msg.Change == unix.IFF_UP {
				//				fmt.Printf("dellink %#+v\n", msg)
				servers.Lock()
				name := msg.Attrs().Name[3:]
				if s, ok := servers.Get(name); ok {
					go func() {
						defer func() {
							if r := recover(); r != nil {
								err, ok := r.(error)
								if !ok {
									err = fmt.Errorf("pkg: %v", r)
								}
								fmt.Printf(err.Error())
							}
						}()
						if err := s.Stop(true); err != nil {
							panic(err)
						}
					}()
				}
				servers.Unlock()
				//				}
			}
		}
	}

}
Пример #7
0
func TestInterfaces(t *testing.T) {
	hoverServer := hover.NewServer()
	defer hoverServer.Close()
	hover := httptest.NewServer(hoverServer.Handler())
	defer hover.Close()
	upstream := httptest.NewServer(newMockUpstream())
	defer upstream.Close()
	g, err := NewServer(upstream.URL, hover.URL)
	if err != nil {
		t.Fatal(err)
	}
	srv := httptest.NewServer(g.Handler())
	defer srv.Close()

	// launch one policy dataplane
	testOne(t, testCase{
		url:  srv.URL + "/policies/",
		body: strings.NewReader(`{"resolved-policy-uri": "` + basicResolvedPolicyUri + `"}`),
		code: http.StatusOK,
	}, nil)

	// set up docker prereqs
	runTestCommand(t, "bash -ex", strings.NewReader(dockerSetup))

	// monitor for netlink updates to find docker veth
	ch, done := make(chan netlink.LinkUpdate), make(chan struct{})
	defer close(done)
	if err := netlink.LinkSubscribe(ch, done); err != nil {
		t.Error(err)
	}

	id1, id2 := "TestInterfaces-1", "TestInterfaces-2"
	// spawn one test server process
	runTestCommand(t, "docker run --name="+id1+" -d moutten/iperf", nil)
	defer runCommand("docker rm -f "+id1, nil)

	link1 := gatherOneLink(t, ch)
	testOne(t, testCase{
		url:  fmt.Sprintf("%s/modules/host/interfaces/%s/policies/", hover.URL, link1.Attrs().Name),
		body: strings.NewReader(fmt.Sprintf(`{"module": "%s"}`, g.dataplane.Id())),
		code: http.StatusOK,
	}, nil)

	// find the ip of the test server
	ip1 := runTestCommand(t, "docker inspect -f {{.NetworkSettings.IPAddress}} "+id1, nil)

	// start a test client
	clientCmd, clientStdin, clientOutput := startCommand(t, "docker run -i --name="+id2+" --entrypoint /bin/sh moutten/iperf -ex")
	defer runCommand("docker rm -f "+id2, nil)

	link2 := gatherOneLink(t, ch)

	ip2 := runTestCommand(t, "docker inspect -f {{.NetworkSettings.IPAddress}} "+id2, nil)
	Debug.Printf("ip2=%s\n", ip2)

	testOne(t, testCase{
		url:  fmt.Sprintf("%s/modules/host/interfaces/%s/policies/", hover.URL, link2.Attrs().Name),
		body: strings.NewReader(fmt.Sprintf(`{"module": "%s"}`, g.dataplane.Id())),
		code: http.StatusOK,
	}, nil)

	if err := g.dataplane.AddEndpoint(ip1, "pepsi", "webservers"); err != nil {
		t.Fatal(err)
	}
	if err := g.dataplane.AddEndpoint(ip2, "pepsi", "clients"); err != nil {
		t.Fatal(err)
	}

	Debug.Println("Endpoints:")
	for endpoint := range g.dataplane.Endpoints() {
		Debug.Printf("%v\n", *endpoint)
	}

	clientStdin.Write([]byte("iperf -t 2 -c " + ip1 + "\n"))
	clientStdin.Close()
	if err := clientCmd.Wait(); err != nil {
		Error.Print(clientOutput.String())
		t.Fatal(err)
	}
	Debug.Print(clientOutput.String())
}