func (r *Router) AddRouter(router *Router) error {
	r.mutex.Lock()
	defer r.mutex.Unlock()
	err := r.addNIC(router)
	if err != nil {
		return err
	}
	if err = router.setRouter(r); err != nil {
		return err
	}
	r.children = append(r.children, router)
	return nil
}
AddRouter adds a chile Router.
package vnet
import (
	"fmt"
	"math/rand"
	"net"
	"strings"
	"sync"
	"sync/atomic"
	"time"
	"github.com/pion/logging"
)
const (
	defaultRouterQueueSize = 0  
)
var assignRouterName = func() func() string {
	var routerIDCtr uint64
	return func() string {
		n := atomic.AddUint64(&routerIDCtr, 1)
		return fmt.Sprintf("router%d", n)
	}
}()
type RouterConfig struct {
	Name string
	CIDR string
	StaticIPs []string
	StaticIP string
	QueueSize int
	NATType *NATType
	MinDelay time.Duration
	MaxJitter time.Duration
	LoggerFactory logging.LoggerFactory
}
type NIC interface {
	getInterface(ifName string) (*Interface, error)
	onInboundChunk(c Chunk)
	getStaticIPs() []net.IP
	setRouter(r *Router) error
}
type ChunkFilter func(c Chunk) bool
type Router struct {
	name           string                     
	interfaces     []*Interface               
	ipv4Net        *net.IPNet                 
	staticIPs      []net.IP                   
	staticLocalIPs map[string]net.IP          
	lastID         byte                       
	queue          *chunkQueue                
	parent         *Router                    
	children       []*Router                  
	natType        *NATType                   
	nat            *networkAddressTranslator  
	nics           map[string]NIC             
	stopFunc       func()                     
	resolver       *resolver                  
	chunkFilters   []ChunkFilter              
	minDelay       time.Duration              
	maxJitter      time.Duration              
	mutex          sync.RWMutex               
	pushCh         chan struct{}              
	loggerFactory  logging.LoggerFactory      
	log            logging.LeveledLogger      
}
func NewRouter(config *RouterConfig) (*Router, error) {
	loggerFactory := config.LoggerFactory
	log := loggerFactory.NewLogger("vnet")
	_, ipv4Net, err := net.ParseCIDR(config.CIDR)
	if err != nil {
		return nil, err
	}
	queueSize := defaultRouterQueueSize
	if config.QueueSize > 0 {
		queueSize = config.QueueSize
	}
	lo0 := NewInterface(net.Interface{
		Index:        1,
		MTU:          16384,
		Name:         "lo0",
		HardwareAddr: nil,
		Flags:        net.FlagUp | net.FlagLoopback | net.FlagMulticast,
	})
	lo0.AddAddr(&net.IPAddr{IP: net.ParseIP("127.0.0.1"), Zone: ""})
	eth0 := NewInterface(net.Interface{
		Index:        2,
		MTU:          1500,
		Name:         "eth0",
		HardwareAddr: newMACAddress(),
		Flags:        net.FlagUp | net.FlagMulticast,
	})
	resolver := newResolver(&resolverConfig{
		LoggerFactory: config.LoggerFactory,
	})
	name := config.Name
	if len(name) == 0 {
		name = assignRouterName()
	}
	var staticIPs []net.IP
	staticLocalIPs := map[string]net.IP{}
	for _, ipStr := range config.StaticIPs {
		ipPair := strings.Split(ipStr, "/")
		if ip := net.ParseIP(ipPair[0]); ip != nil {
			if len(ipPair) > 1 {
				locIP := net.ParseIP(ipPair[1])
				if locIP == nil {
					return nil, fmt.Errorf("invalid local IP in StaticIPs")
				}
				if !ipv4Net.Contains(locIP) {
					return nil, fmt.Errorf("local IP %s mapped in StaticIPs is beyond subnet", locIP.String())
				}
				staticLocalIPs[ip.String()] = locIP
			}
			staticIPs = append(staticIPs, ip)
		}
	}
	if len(config.StaticIP) > 0 {
		log.Warn("StaticIP is deprecated. Use StaticIPs instead")
		if ip := net.ParseIP(config.StaticIP); ip != nil {
			staticIPs = append(staticIPs, ip)
		}
	}
	if nStaticLocal := len(staticLocalIPs); nStaticLocal > 0 {
		if nStaticLocal != len(staticIPs) {
			return nil, fmt.Errorf("all StaticIPs must have associated local IPs")
		}
	}
	return &Router{
		name:           name,
		interfaces:     []*Interface{lo0, eth0},
		ipv4Net:        ipv4Net,
		staticIPs:      staticIPs,
		staticLocalIPs: staticLocalIPs,
		queue:          newChunkQueue(queueSize),
		natType:        config.NATType,
		nics:           map[string]NIC{},
		resolver:       resolver,
		minDelay:       config.MinDelay,
		maxJitter:      config.MaxJitter,
		pushCh:         make(chan struct{}, 1),
		loggerFactory:  loggerFactory,
		log:            log,
	}, nil
}
func (r *Router) getInterfaces() ([]*Interface, error) {
	if len(r.interfaces) == 0 {
		return nil, fmt.Errorf("no interface is available")
	}
	return r.interfaces, nil
}
func (r *Router) getInterface(ifName string) (*Interface, error) {
	r.mutex.RLock()
	defer r.mutex.RUnlock()
	ifs, err := r.getInterfaces()
	if err != nil {
		return nil, err
	}
	for _, ifc := range ifs {
		if ifc.Name == ifName {
			return ifc, nil
		}
	}
	return nil, fmt.Errorf("interface %s not found", ifName)
}
func (r *Router) Start() error {
	r.mutex.Lock()
	defer r.mutex.Unlock()
	if r.stopFunc != nil {
		return fmt.Errorf("router already staretd")
	}
	cancelCh := make(chan struct{})
	go func() {
	loop:
		for {
			d, err := r.processChunks()
			if err != nil {
				r.log.Errorf("[%s] %s", r.name, err.Error())
				break
			}
			if d <= 0 {
				select {
				case <-r.pushCh:
				case <-cancelCh:
					break loop
				}
			} else {
				t := time.NewTimer(d)
				select {
				case <-t.C:
				case <-cancelCh:
					break loop
				}
			}
		}
	}()
	r.stopFunc = func() {
		close(cancelCh)
	}
	for _, child := range r.children {
		if err := child.Start(); err != nil {
			return err
		}
	}
	return nil
}
func (r *Router) Stop() error {
	r.mutex.Lock()
	defer r.mutex.Unlock()
	if r.stopFunc == nil {
		return fmt.Errorf("router already stopped")
	}
	for _, router := range r.children {
		r.mutex.Unlock()
		err := router.Stop()
		r.mutex.Lock()
		if err != nil {
			return err
		}
	}
	r.stopFunc()
	r.stopFunc = nil
	return nil
}
func (r *Router) addNIC(nic NIC) error {
	ifc, err := nic.getInterface("eth0")
	if err != nil {
		return err
	}
	var ips []net.IP
	if ips = nic.getStaticIPs(); len(ips) == 0 {
		ip, err2 := r.assignIPAddress()
		if err2 != nil {
			return err2
		}
		ips = append(ips, ip)
	}
	for _, ip := range ips {
		if !r.ipv4Net.Contains(ip) {
			return fmt.Errorf("static IP is beyond subnet: %s", r.ipv4Net.String())
		}
		ifc.AddAddr(&net.IPNet{
			IP:   ip,
			Mask: r.ipv4Net.Mask,
		})
		r.nics[ip.String()] = nic
	}
	if err = nic.setRouter(r); err != nil {
		return err
	}
	return nil
}