github.com/osrg/gobgp@v2.0.0+incompatible/internal/pkg/table/policy.go (about)

     1  // Copyright (C) 2014-2016 Nippon Telegraph and Telephone Corporation.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //    http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
    12  // implied.
    13  // See the License for the specific language governing permissions and
    14  // limitations under the License.
    15  
    16  package table
    17  
    18  import (
    19  	"bytes"
    20  	"encoding/json"
    21  	"fmt"
    22  	"net"
    23  	"reflect"
    24  	"regexp"
    25  	"sort"
    26  	"strconv"
    27  	"strings"
    28  	"sync"
    29  
    30  	radix "github.com/armon/go-radix"
    31  	api "github.com/osrg/gobgp/api"
    32  	"github.com/osrg/gobgp/internal/pkg/config"
    33  	"github.com/osrg/gobgp/pkg/packet/bgp"
    34  	log "github.com/sirupsen/logrus"
    35  )
    36  
    37  type PolicyOptions struct {
    38  	Info             *PeerInfo
    39  	ValidationResult *Validation
    40  	OldNextHop       net.IP
    41  }
    42  
    43  type DefinedType int
    44  
    45  const (
    46  	DEFINED_TYPE_PREFIX DefinedType = iota
    47  	DEFINED_TYPE_NEIGHBOR
    48  	DEFINED_TYPE_TAG
    49  	DEFINED_TYPE_AS_PATH
    50  	DEFINED_TYPE_COMMUNITY
    51  	DEFINED_TYPE_EXT_COMMUNITY
    52  	DEFINED_TYPE_LARGE_COMMUNITY
    53  	DEFINED_TYPE_NEXT_HOP
    54  )
    55  
    56  type RouteType int
    57  
    58  const (
    59  	ROUTE_TYPE_NONE RouteType = iota
    60  	ROUTE_TYPE_ACCEPT
    61  	ROUTE_TYPE_REJECT
    62  )
    63  
    64  func (t RouteType) String() string {
    65  	switch t {
    66  	case ROUTE_TYPE_NONE:
    67  		return "continue"
    68  	case ROUTE_TYPE_ACCEPT:
    69  		return "accept"
    70  	case ROUTE_TYPE_REJECT:
    71  		return "reject"
    72  	}
    73  	return fmt.Sprintf("unknown(%d)", t)
    74  }
    75  
    76  type PolicyDirection int
    77  
    78  const (
    79  	POLICY_DIRECTION_NONE PolicyDirection = iota
    80  	POLICY_DIRECTION_IMPORT
    81  	POLICY_DIRECTION_EXPORT
    82  )
    83  
    84  func (d PolicyDirection) String() string {
    85  	switch d {
    86  	case POLICY_DIRECTION_IMPORT:
    87  		return "import"
    88  	case POLICY_DIRECTION_EXPORT:
    89  		return "export"
    90  	}
    91  	return fmt.Sprintf("unknown(%d)", d)
    92  }
    93  
    94  type MatchOption int
    95  
    96  const (
    97  	MATCH_OPTION_ANY MatchOption = iota
    98  	MATCH_OPTION_ALL
    99  	MATCH_OPTION_INVERT
   100  )
   101  
   102  func (o MatchOption) String() string {
   103  	switch o {
   104  	case MATCH_OPTION_ANY:
   105  		return "any"
   106  	case MATCH_OPTION_ALL:
   107  		return "all"
   108  	case MATCH_OPTION_INVERT:
   109  		return "invert"
   110  	default:
   111  		return fmt.Sprintf("MatchOption(%d)", o)
   112  	}
   113  }
   114  
   115  func (o MatchOption) ConvertToMatchSetOptionsRestrictedType() config.MatchSetOptionsRestrictedType {
   116  	switch o {
   117  	case MATCH_OPTION_ANY:
   118  		return config.MATCH_SET_OPTIONS_RESTRICTED_TYPE_ANY
   119  	case MATCH_OPTION_INVERT:
   120  		return config.MATCH_SET_OPTIONS_RESTRICTED_TYPE_INVERT
   121  	}
   122  	return "unknown"
   123  }
   124  
   125  type MedActionType int
   126  
   127  const (
   128  	MED_ACTION_MOD MedActionType = iota
   129  	MED_ACTION_REPLACE
   130  )
   131  
   132  var CommunityOptionNameMap = map[config.BgpSetCommunityOptionType]string{
   133  	config.BGP_SET_COMMUNITY_OPTION_TYPE_ADD:     "add",
   134  	config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE:  "remove",
   135  	config.BGP_SET_COMMUNITY_OPTION_TYPE_REPLACE: "replace",
   136  }
   137  
   138  var CommunityOptionValueMap = map[string]config.BgpSetCommunityOptionType{
   139  	CommunityOptionNameMap[config.BGP_SET_COMMUNITY_OPTION_TYPE_ADD]:     config.BGP_SET_COMMUNITY_OPTION_TYPE_ADD,
   140  	CommunityOptionNameMap[config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE]:  config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE,
   141  	CommunityOptionNameMap[config.BGP_SET_COMMUNITY_OPTION_TYPE_REPLACE]: config.BGP_SET_COMMUNITY_OPTION_TYPE_REPLACE,
   142  }
   143  
   144  type ConditionType int
   145  
   146  const (
   147  	CONDITION_PREFIX ConditionType = iota
   148  	CONDITION_NEIGHBOR
   149  	CONDITION_AS_PATH
   150  	CONDITION_COMMUNITY
   151  	CONDITION_EXT_COMMUNITY
   152  	CONDITION_AS_PATH_LENGTH
   153  	CONDITION_RPKI
   154  	CONDITION_ROUTE_TYPE
   155  	CONDITION_LARGE_COMMUNITY
   156  	CONDITION_NEXT_HOP
   157  	CONDITION_AFI_SAFI_IN
   158  )
   159  
   160  type ActionType int
   161  
   162  const (
   163  	ACTION_ROUTING ActionType = iota
   164  	ACTION_COMMUNITY
   165  	ACTION_EXT_COMMUNITY
   166  	ACTION_MED
   167  	ACTION_AS_PATH_PREPEND
   168  	ACTION_NEXTHOP
   169  	ACTION_LOCAL_PREF
   170  	ACTION_LARGE_COMMUNITY
   171  )
   172  
   173  func NewMatchOption(c interface{}) (MatchOption, error) {
   174  	switch t := c.(type) {
   175  	case config.MatchSetOptionsType:
   176  		t = t.DefaultAsNeeded()
   177  		switch t {
   178  		case config.MATCH_SET_OPTIONS_TYPE_ANY:
   179  			return MATCH_OPTION_ANY, nil
   180  		case config.MATCH_SET_OPTIONS_TYPE_ALL:
   181  			return MATCH_OPTION_ALL, nil
   182  		case config.MATCH_SET_OPTIONS_TYPE_INVERT:
   183  			return MATCH_OPTION_INVERT, nil
   184  		}
   185  	case config.MatchSetOptionsRestrictedType:
   186  		t = t.DefaultAsNeeded()
   187  		switch t {
   188  		case config.MATCH_SET_OPTIONS_RESTRICTED_TYPE_ANY:
   189  			return MATCH_OPTION_ANY, nil
   190  		case config.MATCH_SET_OPTIONS_RESTRICTED_TYPE_INVERT:
   191  			return MATCH_OPTION_INVERT, nil
   192  		}
   193  	}
   194  	return MATCH_OPTION_ANY, fmt.Errorf("invalid argument to create match option: %v", c)
   195  }
   196  
   197  type AttributeComparison int
   198  
   199  const (
   200  	// "== comparison"
   201  	ATTRIBUTE_EQ AttributeComparison = iota
   202  	// ">= comparison"
   203  	ATTRIBUTE_GE
   204  	// "<= comparison"
   205  	ATTRIBUTE_LE
   206  )
   207  
   208  func (c AttributeComparison) String() string {
   209  	switch c {
   210  	case ATTRIBUTE_EQ:
   211  		return "="
   212  	case ATTRIBUTE_GE:
   213  		return ">="
   214  	case ATTRIBUTE_LE:
   215  		return "<="
   216  	}
   217  	return "?"
   218  }
   219  
   220  const (
   221  	ASPATH_REGEXP_MAGIC = "(^|[,{}() ]|$)"
   222  )
   223  
   224  type DefinedSet interface {
   225  	Type() DefinedType
   226  	Name() string
   227  	Append(DefinedSet) error
   228  	Remove(DefinedSet) error
   229  	Replace(DefinedSet) error
   230  	String() string
   231  	List() []string
   232  }
   233  
   234  type DefinedSetMap map[DefinedType]map[string]DefinedSet
   235  
   236  type DefinedSetList []DefinedSet
   237  
   238  func (l DefinedSetList) Len() int {
   239  	return len(l)
   240  }
   241  
   242  func (l DefinedSetList) Swap(i, j int) {
   243  	l[i], l[j] = l[j], l[i]
   244  }
   245  
   246  func (l DefinedSetList) Less(i, j int) bool {
   247  	if l[i].Type() != l[j].Type() {
   248  		return l[i].Type() < l[j].Type()
   249  	}
   250  	return l[i].Name() < l[j].Name()
   251  }
   252  
   253  type Prefix struct {
   254  	Prefix             *net.IPNet
   255  	AddressFamily      bgp.RouteFamily
   256  	MasklengthRangeMax uint8
   257  	MasklengthRangeMin uint8
   258  }
   259  
   260  func (p *Prefix) Match(path *Path) bool {
   261  	rf := path.GetRouteFamily()
   262  	if rf != p.AddressFamily {
   263  		return false
   264  	}
   265  
   266  	var pAddr net.IP
   267  	var pMasklen uint8
   268  	switch rf {
   269  	case bgp.RF_IPv4_UC:
   270  		pAddr = path.GetNlri().(*bgp.IPAddrPrefix).Prefix
   271  		pMasklen = path.GetNlri().(*bgp.IPAddrPrefix).Length
   272  	case bgp.RF_IPv6_UC:
   273  		pAddr = path.GetNlri().(*bgp.IPv6AddrPrefix).Prefix
   274  		pMasklen = path.GetNlri().(*bgp.IPv6AddrPrefix).Length
   275  	default:
   276  		return false
   277  	}
   278  
   279  	return (p.MasklengthRangeMin <= pMasklen && pMasklen <= p.MasklengthRangeMax) && p.Prefix.Contains(pAddr)
   280  }
   281  
   282  func (lhs *Prefix) Equal(rhs *Prefix) bool {
   283  	if lhs == rhs {
   284  		return true
   285  	}
   286  	if rhs == nil {
   287  		return false
   288  	}
   289  	return lhs.Prefix.String() == rhs.Prefix.String() && lhs.MasklengthRangeMin == rhs.MasklengthRangeMin && lhs.MasklengthRangeMax == rhs.MasklengthRangeMax
   290  }
   291  
   292  func (p *Prefix) PrefixString() string {
   293  	isZeros := func(p net.IP) bool {
   294  		for i := 0; i < len(p); i++ {
   295  			if p[i] != 0 {
   296  				return false
   297  			}
   298  		}
   299  		return true
   300  	}
   301  
   302  	ip := p.Prefix.IP
   303  	if p.AddressFamily == bgp.RF_IPv6_UC && isZeros(ip[0:10]) && ip[10] == 0xff && ip[11] == 0xff {
   304  		m, _ := p.Prefix.Mask.Size()
   305  		return fmt.Sprintf("::FFFF:%s/%d", ip.To16(), m)
   306  	}
   307  	return p.Prefix.String()
   308  }
   309  
   310  var _regexpPrefixRange = regexp.MustCompile(`(\d+)\.\.(\d+)`)
   311  
   312  func NewPrefix(c config.Prefix) (*Prefix, error) {
   313  	_, prefix, err := net.ParseCIDR(c.IpPrefix)
   314  	if err != nil {
   315  		return nil, err
   316  	}
   317  
   318  	rf := bgp.RF_IPv4_UC
   319  	if strings.Contains(c.IpPrefix, ":") {
   320  		rf = bgp.RF_IPv6_UC
   321  	}
   322  	p := &Prefix{
   323  		Prefix:        prefix,
   324  		AddressFamily: rf,
   325  	}
   326  	maskRange := c.MasklengthRange
   327  
   328  	if maskRange == "" {
   329  		l, _ := prefix.Mask.Size()
   330  		maskLength := uint8(l)
   331  		p.MasklengthRangeMax = maskLength
   332  		p.MasklengthRangeMin = maskLength
   333  		return p, nil
   334  	}
   335  
   336  	elems := _regexpPrefixRange.FindStringSubmatch(maskRange)
   337  	if len(elems) != 3 {
   338  		log.WithFields(log.Fields{
   339  			"Topic":           "Policy",
   340  			"Type":            "Prefix",
   341  			"MaskRangeFormat": maskRange,
   342  		}).Warn("mask length range format is invalid.")
   343  		return nil, fmt.Errorf("mask length range format is invalid")
   344  	}
   345  
   346  	// we've already checked the range is sane by regexp
   347  	min, _ := strconv.ParseUint(elems[1], 10, 8)
   348  	max, _ := strconv.ParseUint(elems[2], 10, 8)
   349  	p.MasklengthRangeMin = uint8(min)
   350  	p.MasklengthRangeMax = uint8(max)
   351  	return p, nil
   352  }
   353  
   354  type PrefixSet struct {
   355  	name   string
   356  	tree   *radix.Tree
   357  	family bgp.RouteFamily
   358  }
   359  
   360  func (s *PrefixSet) Name() string {
   361  	return s.name
   362  }
   363  
   364  func (s *PrefixSet) Type() DefinedType {
   365  	return DEFINED_TYPE_PREFIX
   366  }
   367  
   368  func (lhs *PrefixSet) Append(arg DefinedSet) error {
   369  	rhs, ok := arg.(*PrefixSet)
   370  	if !ok {
   371  		return fmt.Errorf("type cast failed")
   372  	}
   373  
   374  	if rhs.tree.Len() == 0 {
   375  		// if try to append an empty set, then return directly
   376  		return nil
   377  	}
   378  
   379  	// if either is empty, family can be ignored.
   380  	if lhs.tree.Len() != 0 && rhs.tree.Len() != 0 {
   381  		_, w, _ := lhs.tree.Minimum()
   382  		l := w.([]*Prefix)
   383  		_, v, _ := rhs.tree.Minimum()
   384  		r := v.([]*Prefix)
   385  		if l[0].AddressFamily != r[0].AddressFamily {
   386  			return fmt.Errorf("can't append different family")
   387  		}
   388  	}
   389  	rhs.tree.Walk(func(key string, v interface{}) bool {
   390  		w, ok := lhs.tree.Get(key)
   391  		if ok {
   392  			r := v.([]*Prefix)
   393  			l := w.([]*Prefix)
   394  			lhs.tree.Insert(key, append(l, r...))
   395  		} else {
   396  			lhs.tree.Insert(key, v)
   397  		}
   398  		return false
   399  	})
   400  	_, w, _ := lhs.tree.Minimum()
   401  	lhs.family = w.([]*Prefix)[0].AddressFamily
   402  	return nil
   403  }
   404  
   405  func (lhs *PrefixSet) Remove(arg DefinedSet) error {
   406  	rhs, ok := arg.(*PrefixSet)
   407  	if !ok {
   408  		return fmt.Errorf("type cast failed")
   409  	}
   410  	rhs.tree.Walk(func(key string, v interface{}) bool {
   411  		w, ok := lhs.tree.Get(key)
   412  		if !ok {
   413  			return false
   414  		}
   415  		r := v.([]*Prefix)
   416  		l := w.([]*Prefix)
   417  		new := make([]*Prefix, 0, len(l))
   418  		for _, lp := range l {
   419  			delete := false
   420  			for _, rp := range r {
   421  				if lp.Equal(rp) {
   422  					delete = true
   423  					break
   424  				}
   425  			}
   426  			if !delete {
   427  				new = append(new, lp)
   428  			}
   429  		}
   430  		if len(new) == 0 {
   431  			lhs.tree.Delete(key)
   432  		} else {
   433  			lhs.tree.Insert(key, new)
   434  		}
   435  		return false
   436  	})
   437  	return nil
   438  }
   439  
   440  func (lhs *PrefixSet) Replace(arg DefinedSet) error {
   441  	rhs, ok := arg.(*PrefixSet)
   442  	if !ok {
   443  		return fmt.Errorf("type cast failed")
   444  	}
   445  	lhs.tree = rhs.tree
   446  	lhs.family = rhs.family
   447  	return nil
   448  }
   449  
   450  func (s *PrefixSet) List() []string {
   451  	var list []string
   452  	s.tree.Walk(func(s string, v interface{}) bool {
   453  		ps := v.([]*Prefix)
   454  		for _, p := range ps {
   455  			list = append(list, fmt.Sprintf("%s %d..%d", p.PrefixString(), p.MasklengthRangeMin, p.MasklengthRangeMax))
   456  		}
   457  		return false
   458  	})
   459  	return list
   460  }
   461  
   462  func (s *PrefixSet) ToConfig() *config.PrefixSet {
   463  	list := make([]config.Prefix, 0, s.tree.Len())
   464  	s.tree.Walk(func(s string, v interface{}) bool {
   465  		ps := v.([]*Prefix)
   466  		for _, p := range ps {
   467  			list = append(list, config.Prefix{IpPrefix: p.PrefixString(), MasklengthRange: fmt.Sprintf("%d..%d", p.MasklengthRangeMin, p.MasklengthRangeMax)})
   468  		}
   469  		return false
   470  	})
   471  	return &config.PrefixSet{
   472  		PrefixSetName: s.name,
   473  		PrefixList:    list,
   474  	}
   475  }
   476  
   477  func (s *PrefixSet) String() string {
   478  	return strings.Join(s.List(), "\n")
   479  }
   480  
   481  func (s *PrefixSet) MarshalJSON() ([]byte, error) {
   482  	return json.Marshal(s.ToConfig())
   483  }
   484  
   485  func NewPrefixSetFromApiStruct(name string, prefixes []*Prefix) (*PrefixSet, error) {
   486  	if name == "" {
   487  		return nil, fmt.Errorf("empty prefix set name")
   488  	}
   489  	tree := radix.New()
   490  	var family bgp.RouteFamily
   491  	for i, x := range prefixes {
   492  		if i == 0 {
   493  			family = x.AddressFamily
   494  		} else if family != x.AddressFamily {
   495  			return nil, fmt.Errorf("multiple families")
   496  		}
   497  		key := CidrToRadixkey(x.Prefix.String())
   498  		d, ok := tree.Get(key)
   499  		if ok {
   500  			ps := d.([]*Prefix)
   501  			tree.Insert(key, append(ps, x))
   502  		} else {
   503  			tree.Insert(key, []*Prefix{x})
   504  		}
   505  	}
   506  	return &PrefixSet{
   507  		name:   name,
   508  		tree:   tree,
   509  		family: family,
   510  	}, nil
   511  }
   512  
   513  func NewPrefixSet(c config.PrefixSet) (*PrefixSet, error) {
   514  	name := c.PrefixSetName
   515  	if name == "" {
   516  		if len(c.PrefixList) == 0 {
   517  			return nil, nil
   518  		}
   519  		return nil, fmt.Errorf("empty prefix set name")
   520  	}
   521  	tree := radix.New()
   522  	var family bgp.RouteFamily
   523  	for i, x := range c.PrefixList {
   524  		y, err := NewPrefix(x)
   525  		if err != nil {
   526  			return nil, err
   527  		}
   528  		if i == 0 {
   529  			family = y.AddressFamily
   530  		} else if family != y.AddressFamily {
   531  			return nil, fmt.Errorf("multiple families")
   532  		}
   533  		key := CidrToRadixkey(y.Prefix.String())
   534  		d, ok := tree.Get(key)
   535  		if ok {
   536  			ps := d.([]*Prefix)
   537  			tree.Insert(key, append(ps, y))
   538  		} else {
   539  			tree.Insert(key, []*Prefix{y})
   540  		}
   541  	}
   542  	return &PrefixSet{
   543  		name:   name,
   544  		tree:   tree,
   545  		family: family,
   546  	}, nil
   547  }
   548  
   549  type NextHopSet struct {
   550  	list []net.IPNet
   551  }
   552  
   553  func (s *NextHopSet) Name() string {
   554  	return "NextHopSet: NO NAME"
   555  }
   556  
   557  func (s *NextHopSet) Type() DefinedType {
   558  	return DEFINED_TYPE_NEXT_HOP
   559  }
   560  
   561  func (lhs *NextHopSet) Append(arg DefinedSet) error {
   562  	rhs, ok := arg.(*NextHopSet)
   563  	if !ok {
   564  		return fmt.Errorf("type cast failed")
   565  	}
   566  	lhs.list = append(lhs.list, rhs.list...)
   567  	return nil
   568  }
   569  
   570  func (lhs *NextHopSet) Remove(arg DefinedSet) error {
   571  	rhs, ok := arg.(*NextHopSet)
   572  	if !ok {
   573  		return fmt.Errorf("type cast failed")
   574  	}
   575  	ps := make([]net.IPNet, 0, len(lhs.list))
   576  	for _, x := range lhs.list {
   577  		found := false
   578  		for _, y := range rhs.list {
   579  			if x.String() == y.String() {
   580  				found = true
   581  				break
   582  			}
   583  		}
   584  		if !found {
   585  			ps = append(ps, x)
   586  		}
   587  	}
   588  	lhs.list = ps
   589  	return nil
   590  }
   591  
   592  func (lhs *NextHopSet) Replace(arg DefinedSet) error {
   593  	rhs, ok := arg.(*NextHopSet)
   594  	if !ok {
   595  		return fmt.Errorf("type cast failed")
   596  	}
   597  	lhs.list = rhs.list
   598  	return nil
   599  }
   600  
   601  func (s *NextHopSet) List() []string {
   602  	list := make([]string, 0, len(s.list))
   603  	for _, n := range s.list {
   604  		list = append(list, n.String())
   605  	}
   606  	return list
   607  }
   608  
   609  func (s *NextHopSet) ToConfig() []string {
   610  	return s.List()
   611  }
   612  
   613  func (s *NextHopSet) String() string {
   614  	return "[ " + strings.Join(s.List(), ", ") + " ]"
   615  }
   616  
   617  func (s *NextHopSet) MarshalJSON() ([]byte, error) {
   618  	return json.Marshal(s.ToConfig())
   619  }
   620  
   621  func NewNextHopSetFromApiStruct(name string, list []net.IPNet) (*NextHopSet, error) {
   622  	return &NextHopSet{
   623  		list: list,
   624  	}, nil
   625  }
   626  
   627  func NewNextHopSet(c []string) (*NextHopSet, error) {
   628  	list := make([]net.IPNet, 0, len(c))
   629  	for _, x := range c {
   630  		_, cidr, err := net.ParseCIDR(x)
   631  		if err != nil {
   632  			addr := net.ParseIP(x)
   633  			if addr == nil {
   634  				return nil, fmt.Errorf("invalid address or prefix: %s", x)
   635  			}
   636  			mask := net.CIDRMask(32, 32)
   637  			if addr.To4() == nil {
   638  				mask = net.CIDRMask(128, 128)
   639  			}
   640  			cidr = &net.IPNet{
   641  				IP:   addr,
   642  				Mask: mask,
   643  			}
   644  		}
   645  		list = append(list, *cidr)
   646  	}
   647  	return &NextHopSet{
   648  		list: list,
   649  	}, nil
   650  }
   651  
   652  type NeighborSet struct {
   653  	name string
   654  	list []net.IPNet
   655  }
   656  
   657  func (s *NeighborSet) Name() string {
   658  	return s.name
   659  }
   660  
   661  func (s *NeighborSet) Type() DefinedType {
   662  	return DEFINED_TYPE_NEIGHBOR
   663  }
   664  
   665  func (lhs *NeighborSet) Append(arg DefinedSet) error {
   666  	rhs, ok := arg.(*NeighborSet)
   667  	if !ok {
   668  		return fmt.Errorf("type cast failed")
   669  	}
   670  	lhs.list = append(lhs.list, rhs.list...)
   671  	return nil
   672  }
   673  
   674  func (lhs *NeighborSet) Remove(arg DefinedSet) error {
   675  	rhs, ok := arg.(*NeighborSet)
   676  	if !ok {
   677  		return fmt.Errorf("type cast failed")
   678  	}
   679  	ps := make([]net.IPNet, 0, len(lhs.list))
   680  	for _, x := range lhs.list {
   681  		found := false
   682  		for _, y := range rhs.list {
   683  			if x.String() == y.String() {
   684  				found = true
   685  				break
   686  			}
   687  		}
   688  		if !found {
   689  			ps = append(ps, x)
   690  		}
   691  	}
   692  	lhs.list = ps
   693  	return nil
   694  }
   695  
   696  func (lhs *NeighborSet) Replace(arg DefinedSet) error {
   697  	rhs, ok := arg.(*NeighborSet)
   698  	if !ok {
   699  		return fmt.Errorf("type cast failed")
   700  	}
   701  	lhs.list = rhs.list
   702  	return nil
   703  }
   704  
   705  func (s *NeighborSet) List() []string {
   706  	list := make([]string, 0, len(s.list))
   707  	for _, n := range s.list {
   708  		list = append(list, n.String())
   709  	}
   710  	return list
   711  }
   712  
   713  func (s *NeighborSet) ToConfig() *config.NeighborSet {
   714  	return &config.NeighborSet{
   715  		NeighborSetName:  s.name,
   716  		NeighborInfoList: s.List(),
   717  	}
   718  }
   719  
   720  func (s *NeighborSet) String() string {
   721  	return strings.Join(s.List(), "\n")
   722  }
   723  
   724  func (s *NeighborSet) MarshalJSON() ([]byte, error) {
   725  	return json.Marshal(s.ToConfig())
   726  }
   727  
   728  func NewNeighborSetFromApiStruct(name string, list []net.IPNet) (*NeighborSet, error) {
   729  	return &NeighborSet{
   730  		name: name,
   731  		list: list,
   732  	}, nil
   733  }
   734  
   735  func NewNeighborSet(c config.NeighborSet) (*NeighborSet, error) {
   736  	name := c.NeighborSetName
   737  	if name == "" {
   738  		if len(c.NeighborInfoList) == 0 {
   739  			return nil, nil
   740  		}
   741  		return nil, fmt.Errorf("empty neighbor set name")
   742  	}
   743  	list := make([]net.IPNet, 0, len(c.NeighborInfoList))
   744  	for _, x := range c.NeighborInfoList {
   745  		_, cidr, err := net.ParseCIDR(x)
   746  		if err != nil {
   747  			addr := net.ParseIP(x)
   748  			if addr == nil {
   749  				return nil, fmt.Errorf("invalid address or prefix: %s", x)
   750  			}
   751  			mask := net.CIDRMask(32, 32)
   752  			if addr.To4() == nil {
   753  				mask = net.CIDRMask(128, 128)
   754  			}
   755  			cidr = &net.IPNet{
   756  				IP:   addr,
   757  				Mask: mask,
   758  			}
   759  		}
   760  		list = append(list, *cidr)
   761  	}
   762  	return &NeighborSet{
   763  		name: name,
   764  		list: list,
   765  	}, nil
   766  }
   767  
   768  type singleAsPathMatchMode int
   769  
   770  const (
   771  	INCLUDE singleAsPathMatchMode = iota
   772  	LEFT_MOST
   773  	ORIGIN
   774  	ONLY
   775  )
   776  
   777  type singleAsPathMatch struct {
   778  	asn  uint32
   779  	mode singleAsPathMatchMode
   780  }
   781  
   782  func (lhs *singleAsPathMatch) Equal(rhs *singleAsPathMatch) bool {
   783  	return lhs.asn == rhs.asn && lhs.mode == rhs.mode
   784  }
   785  
   786  func (lhs *singleAsPathMatch) String() string {
   787  	switch lhs.mode {
   788  	case INCLUDE:
   789  		return fmt.Sprintf("_%d_", lhs.asn)
   790  	case LEFT_MOST:
   791  		return fmt.Sprintf("^%d_", lhs.asn)
   792  	case ORIGIN:
   793  		return fmt.Sprintf("_%d$", lhs.asn)
   794  	case ONLY:
   795  		return fmt.Sprintf("^%d$", lhs.asn)
   796  	}
   797  	return ""
   798  }
   799  
   800  func (m *singleAsPathMatch) Match(aspath []uint32) bool {
   801  	if len(aspath) == 0 {
   802  		return false
   803  	}
   804  	switch m.mode {
   805  	case INCLUDE:
   806  		for _, asn := range aspath {
   807  			if m.asn == asn {
   808  				return true
   809  			}
   810  		}
   811  	case LEFT_MOST:
   812  		if m.asn == aspath[0] {
   813  			return true
   814  		}
   815  	case ORIGIN:
   816  		if m.asn == aspath[len(aspath)-1] {
   817  			return true
   818  		}
   819  	case ONLY:
   820  		if len(aspath) == 1 && m.asn == aspath[0] {
   821  			return true
   822  		}
   823  	}
   824  	return false
   825  }
   826  
   827  var (
   828  	_regexpLeftMostRe = regexp.MustCompile(`$\^([0-9]+)_^`)
   829  	_regexpOriginRe   = regexp.MustCompile(`^_([0-9]+)\$$`)
   830  	_regexpIncludeRe  = regexp.MustCompile("^_([0-9]+)_$")
   831  	_regexpOnlyRe     = regexp.MustCompile(`^\^([0-9]+)\$$`)
   832  )
   833  
   834  func NewSingleAsPathMatch(arg string) *singleAsPathMatch {
   835  	switch {
   836  	case _regexpLeftMostRe.MatchString(arg):
   837  		asn, _ := strconv.ParseUint(_regexpLeftMostRe.FindStringSubmatch(arg)[1], 10, 32)
   838  		return &singleAsPathMatch{
   839  			asn:  uint32(asn),
   840  			mode: LEFT_MOST,
   841  		}
   842  	case _regexpOriginRe.MatchString(arg):
   843  		asn, _ := strconv.ParseUint(_regexpOriginRe.FindStringSubmatch(arg)[1], 10, 32)
   844  		return &singleAsPathMatch{
   845  			asn:  uint32(asn),
   846  			mode: ORIGIN,
   847  		}
   848  	case _regexpIncludeRe.MatchString(arg):
   849  		asn, _ := strconv.ParseUint(_regexpIncludeRe.FindStringSubmatch(arg)[1], 10, 32)
   850  		return &singleAsPathMatch{
   851  			asn:  uint32(asn),
   852  			mode: INCLUDE,
   853  		}
   854  	case _regexpOnlyRe.MatchString(arg):
   855  		asn, _ := strconv.ParseUint(_regexpOnlyRe.FindStringSubmatch(arg)[1], 10, 32)
   856  		return &singleAsPathMatch{
   857  			asn:  uint32(asn),
   858  			mode: ONLY,
   859  		}
   860  	}
   861  	return nil
   862  }
   863  
   864  type AsPathSet struct {
   865  	typ        DefinedType
   866  	name       string
   867  	list       []*regexp.Regexp
   868  	singleList []*singleAsPathMatch
   869  }
   870  
   871  func (s *AsPathSet) Name() string {
   872  	return s.name
   873  }
   874  
   875  func (s *AsPathSet) Type() DefinedType {
   876  	return s.typ
   877  }
   878  
   879  func (lhs *AsPathSet) Append(arg DefinedSet) error {
   880  	if lhs.Type() != arg.Type() {
   881  		return fmt.Errorf("can't append to different type of defined-set")
   882  	}
   883  	lhs.list = append(lhs.list, arg.(*AsPathSet).list...)
   884  	lhs.singleList = append(lhs.singleList, arg.(*AsPathSet).singleList...)
   885  	return nil
   886  }
   887  
   888  func (lhs *AsPathSet) Remove(arg DefinedSet) error {
   889  	if lhs.Type() != arg.Type() {
   890  		return fmt.Errorf("can't append to different type of defined-set")
   891  	}
   892  	newList := make([]*regexp.Regexp, 0, len(lhs.list))
   893  	for _, x := range lhs.list {
   894  		found := false
   895  		for _, y := range arg.(*AsPathSet).list {
   896  			if x.String() == y.String() {
   897  				found = true
   898  				break
   899  			}
   900  		}
   901  		if !found {
   902  			newList = append(newList, x)
   903  		}
   904  	}
   905  	lhs.list = newList
   906  	newSingleList := make([]*singleAsPathMatch, 0, len(lhs.singleList))
   907  	for _, x := range lhs.singleList {
   908  		found := false
   909  		for _, y := range arg.(*AsPathSet).singleList {
   910  			if x.Equal(y) {
   911  				found = true
   912  				break
   913  			}
   914  		}
   915  		if !found {
   916  			newSingleList = append(newSingleList, x)
   917  		}
   918  	}
   919  	lhs.singleList = newSingleList
   920  	return nil
   921  }
   922  
   923  func (lhs *AsPathSet) Replace(arg DefinedSet) error {
   924  	rhs, ok := arg.(*AsPathSet)
   925  	if !ok {
   926  		return fmt.Errorf("type cast failed")
   927  	}
   928  	lhs.list = rhs.list
   929  	lhs.singleList = rhs.singleList
   930  	return nil
   931  }
   932  
   933  func (s *AsPathSet) List() []string {
   934  	list := make([]string, 0, len(s.list)+len(s.singleList))
   935  	for _, exp := range s.singleList {
   936  		list = append(list, exp.String())
   937  	}
   938  	for _, exp := range s.list {
   939  		list = append(list, exp.String())
   940  	}
   941  	return list
   942  }
   943  
   944  func (s *AsPathSet) ToConfig() *config.AsPathSet {
   945  	return &config.AsPathSet{
   946  		AsPathSetName: s.name,
   947  		AsPathList:    s.List(),
   948  	}
   949  }
   950  
   951  func (s *AsPathSet) String() string {
   952  	return strings.Join(s.List(), "\n")
   953  }
   954  
   955  func (s *AsPathSet) MarshalJSON() ([]byte, error) {
   956  	return json.Marshal(s.ToConfig())
   957  }
   958  
   959  func NewAsPathSet(c config.AsPathSet) (*AsPathSet, error) {
   960  	name := c.AsPathSetName
   961  	if name == "" {
   962  		if len(c.AsPathList) == 0 {
   963  			return nil, nil
   964  		}
   965  		return nil, fmt.Errorf("empty as-path set name")
   966  	}
   967  	list := make([]*regexp.Regexp, 0, len(c.AsPathList))
   968  	singleList := make([]*singleAsPathMatch, 0, len(c.AsPathList))
   969  	for _, x := range c.AsPathList {
   970  		if s := NewSingleAsPathMatch(x); s != nil {
   971  			singleList = append(singleList, s)
   972  		} else {
   973  			exp, err := regexp.Compile(strings.Replace(x, "_", ASPATH_REGEXP_MAGIC, -1))
   974  			if err != nil {
   975  				return nil, fmt.Errorf("invalid regular expression: %s", x)
   976  			}
   977  			list = append(list, exp)
   978  		}
   979  	}
   980  	return &AsPathSet{
   981  		typ:        DEFINED_TYPE_AS_PATH,
   982  		name:       name,
   983  		list:       list,
   984  		singleList: singleList,
   985  	}, nil
   986  }
   987  
   988  type regExpSet struct {
   989  	typ  DefinedType
   990  	name string
   991  	list []*regexp.Regexp
   992  }
   993  
   994  func (s *regExpSet) Name() string {
   995  	return s.name
   996  }
   997  
   998  func (s *regExpSet) Type() DefinedType {
   999  	return s.typ
  1000  }
  1001  
  1002  func (lhs *regExpSet) Append(arg DefinedSet) error {
  1003  	if lhs.Type() != arg.Type() {
  1004  		return fmt.Errorf("can't append to different type of defined-set")
  1005  	}
  1006  	var list []*regexp.Regexp
  1007  	switch lhs.Type() {
  1008  	case DEFINED_TYPE_AS_PATH:
  1009  		list = arg.(*AsPathSet).list
  1010  	case DEFINED_TYPE_COMMUNITY:
  1011  		list = arg.(*CommunitySet).list
  1012  	case DEFINED_TYPE_EXT_COMMUNITY:
  1013  		list = arg.(*ExtCommunitySet).list
  1014  	case DEFINED_TYPE_LARGE_COMMUNITY:
  1015  		list = arg.(*LargeCommunitySet).list
  1016  	default:
  1017  		return fmt.Errorf("invalid defined-set type: %d", lhs.Type())
  1018  	}
  1019  	lhs.list = append(lhs.list, list...)
  1020  	return nil
  1021  }
  1022  
  1023  func (lhs *regExpSet) Remove(arg DefinedSet) error {
  1024  	if lhs.Type() != arg.Type() {
  1025  		return fmt.Errorf("can't append to different type of defined-set")
  1026  	}
  1027  	var list []*regexp.Regexp
  1028  	switch lhs.Type() {
  1029  	case DEFINED_TYPE_AS_PATH:
  1030  		list = arg.(*AsPathSet).list
  1031  	case DEFINED_TYPE_COMMUNITY:
  1032  		list = arg.(*CommunitySet).list
  1033  	case DEFINED_TYPE_EXT_COMMUNITY:
  1034  		list = arg.(*ExtCommunitySet).list
  1035  	case DEFINED_TYPE_LARGE_COMMUNITY:
  1036  		list = arg.(*LargeCommunitySet).list
  1037  	default:
  1038  		return fmt.Errorf("invalid defined-set type: %d", lhs.Type())
  1039  	}
  1040  	ps := make([]*regexp.Regexp, 0, len(lhs.list))
  1041  	for _, x := range lhs.list {
  1042  		found := false
  1043  		for _, y := range list {
  1044  			if x.String() == y.String() {
  1045  				found = true
  1046  				break
  1047  			}
  1048  		}
  1049  		if !found {
  1050  			ps = append(ps, x)
  1051  		}
  1052  	}
  1053  	lhs.list = ps
  1054  	return nil
  1055  }
  1056  
  1057  func (lhs *regExpSet) Replace(arg DefinedSet) error {
  1058  	switch c := arg.(type) {
  1059  	case *CommunitySet:
  1060  		lhs.list = c.list
  1061  	case *ExtCommunitySet:
  1062  		lhs.list = c.list
  1063  	case *LargeCommunitySet:
  1064  		lhs.list = c.list
  1065  	default:
  1066  		return fmt.Errorf("type cast failed")
  1067  	}
  1068  	return nil
  1069  }
  1070  
  1071  type CommunitySet struct {
  1072  	regExpSet
  1073  }
  1074  
  1075  func (s *CommunitySet) List() []string {
  1076  	list := make([]string, 0, len(s.list))
  1077  	for _, exp := range s.list {
  1078  		list = append(list, exp.String())
  1079  	}
  1080  	return list
  1081  }
  1082  
  1083  func (s *CommunitySet) ToConfig() *config.CommunitySet {
  1084  	return &config.CommunitySet{
  1085  		CommunitySetName: s.name,
  1086  		CommunityList:    s.List(),
  1087  	}
  1088  }
  1089  
  1090  func (s *CommunitySet) String() string {
  1091  	return strings.Join(s.List(), "\n")
  1092  }
  1093  
  1094  func (s *CommunitySet) MarshalJSON() ([]byte, error) {
  1095  	return json.Marshal(s.ToConfig())
  1096  }
  1097  
  1098  var _regexpCommunity = regexp.MustCompile(`(\d+):(\d+)`)
  1099  
  1100  func ParseCommunity(arg string) (uint32, error) {
  1101  	i, err := strconv.ParseUint(arg, 10, 32)
  1102  	if err == nil {
  1103  		return uint32(i), nil
  1104  	}
  1105  
  1106  	elems := _regexpCommunity.FindStringSubmatch(arg)
  1107  	if len(elems) == 3 {
  1108  		fst, _ := strconv.ParseUint(elems[1], 10, 16)
  1109  		snd, _ := strconv.ParseUint(elems[2], 10, 16)
  1110  		return uint32(fst<<16 | snd), nil
  1111  	}
  1112  	for i, v := range bgp.WellKnownCommunityNameMap {
  1113  		if arg == v {
  1114  			return uint32(i), nil
  1115  		}
  1116  	}
  1117  	return 0, fmt.Errorf("failed to parse %s as community", arg)
  1118  }
  1119  
  1120  func ParseExtCommunity(arg string) (bgp.ExtendedCommunityInterface, error) {
  1121  	var subtype bgp.ExtendedCommunityAttrSubType
  1122  	var value string
  1123  	elems := strings.SplitN(arg, ":", 2)
  1124  
  1125  	isValidationState := func(s string) bool {
  1126  		s = strings.ToLower(s)
  1127  		r := s == bgp.VALIDATION_STATE_VALID.String()
  1128  		r = r || s == bgp.VALIDATION_STATE_NOT_FOUND.String()
  1129  		return r || s == bgp.VALIDATION_STATE_INVALID.String()
  1130  	}
  1131  	if len(elems) < 2 && (len(elems) < 1 && !isValidationState(elems[0])) {
  1132  		return nil, fmt.Errorf("invalid ext-community (rt|soo):<value> | valid | not-found | invalid")
  1133  	}
  1134  	if isValidationState(elems[0]) {
  1135  		subtype = bgp.EC_SUBTYPE_ORIGIN_VALIDATION
  1136  		value = elems[0]
  1137  	} else {
  1138  		switch strings.ToLower(elems[0]) {
  1139  		case "rt":
  1140  			subtype = bgp.EC_SUBTYPE_ROUTE_TARGET
  1141  		case "soo":
  1142  			subtype = bgp.EC_SUBTYPE_ROUTE_ORIGIN
  1143  		default:
  1144  			return nil, fmt.Errorf("invalid ext-community (rt|soo):<value> | valid | not-found | invalid")
  1145  		}
  1146  		value = elems[1]
  1147  	}
  1148  	return bgp.ParseExtendedCommunity(subtype, value)
  1149  }
  1150  
  1151  var _regexpCommunity2 = regexp.MustCompile(`(\d+.)*\d+:\d+`)
  1152  
  1153  func ParseCommunityRegexp(arg string) (*regexp.Regexp, error) {
  1154  	i, err := strconv.ParseUint(arg, 10, 32)
  1155  	if err == nil {
  1156  		return regexp.Compile(fmt.Sprintf("^%d:%d$", i>>16, i&0x0000ffff))
  1157  	}
  1158  
  1159  	if _regexpCommunity2.MatchString(arg) {
  1160  		return regexp.Compile(fmt.Sprintf("^%s$", arg))
  1161  	}
  1162  
  1163  	for i, v := range bgp.WellKnownCommunityNameMap {
  1164  		if strings.Replace(strings.ToLower(arg), "_", "-", -1) == v {
  1165  			return regexp.Compile(fmt.Sprintf("^%d:%d$", i>>16, i&0x0000ffff))
  1166  		}
  1167  	}
  1168  
  1169  	return regexp.Compile(arg)
  1170  }
  1171  
  1172  func ParseExtCommunityRegexp(arg string) (bgp.ExtendedCommunityAttrSubType, *regexp.Regexp, error) {
  1173  	var subtype bgp.ExtendedCommunityAttrSubType
  1174  	elems := strings.SplitN(arg, ":", 2)
  1175  	if len(elems) < 2 {
  1176  		return subtype, nil, fmt.Errorf("invalid ext-community format([rt|soo]:<value>)")
  1177  	}
  1178  	switch strings.ToLower(elems[0]) {
  1179  	case "rt":
  1180  		subtype = bgp.EC_SUBTYPE_ROUTE_TARGET
  1181  	case "soo":
  1182  		subtype = bgp.EC_SUBTYPE_ROUTE_ORIGIN
  1183  	default:
  1184  		return subtype, nil, fmt.Errorf("unknown ext-community subtype. rt, soo is supported")
  1185  	}
  1186  	exp, err := ParseCommunityRegexp(elems[1])
  1187  	return subtype, exp, err
  1188  }
  1189  
  1190  func NewCommunitySet(c config.CommunitySet) (*CommunitySet, error) {
  1191  	name := c.CommunitySetName
  1192  	if name == "" {
  1193  		if len(c.CommunityList) == 0 {
  1194  			return nil, nil
  1195  		}
  1196  		return nil, fmt.Errorf("empty community set name")
  1197  	}
  1198  	list := make([]*regexp.Regexp, 0, len(c.CommunityList))
  1199  	for _, x := range c.CommunityList {
  1200  		exp, err := ParseCommunityRegexp(x)
  1201  		if err != nil {
  1202  			return nil, err
  1203  		}
  1204  		list = append(list, exp)
  1205  	}
  1206  	return &CommunitySet{
  1207  		regExpSet: regExpSet{
  1208  			typ:  DEFINED_TYPE_COMMUNITY,
  1209  			name: name,
  1210  			list: list,
  1211  		},
  1212  	}, nil
  1213  }
  1214  
  1215  type ExtCommunitySet struct {
  1216  	regExpSet
  1217  	subtypeList []bgp.ExtendedCommunityAttrSubType
  1218  }
  1219  
  1220  func (s *ExtCommunitySet) List() []string {
  1221  	list := make([]string, 0, len(s.list))
  1222  	f := func(idx int, arg string) string {
  1223  		switch s.subtypeList[idx] {
  1224  		case bgp.EC_SUBTYPE_ROUTE_TARGET:
  1225  			return fmt.Sprintf("rt:%s", arg)
  1226  		case bgp.EC_SUBTYPE_ROUTE_ORIGIN:
  1227  			return fmt.Sprintf("soo:%s", arg)
  1228  		case bgp.EC_SUBTYPE_ORIGIN_VALIDATION:
  1229  			return arg
  1230  		default:
  1231  			return fmt.Sprintf("%d:%s", s.subtypeList[idx], arg)
  1232  		}
  1233  	}
  1234  	for idx, exp := range s.list {
  1235  		list = append(list, f(idx, exp.String()))
  1236  	}
  1237  	return list
  1238  }
  1239  
  1240  func (s *ExtCommunitySet) ToConfig() *config.ExtCommunitySet {
  1241  	return &config.ExtCommunitySet{
  1242  		ExtCommunitySetName: s.name,
  1243  		ExtCommunityList:    s.List(),
  1244  	}
  1245  }
  1246  
  1247  func (s *ExtCommunitySet) String() string {
  1248  	return strings.Join(s.List(), "\n")
  1249  }
  1250  
  1251  func (s *ExtCommunitySet) MarshalJSON() ([]byte, error) {
  1252  	return json.Marshal(s.ToConfig())
  1253  }
  1254  
  1255  func NewExtCommunitySet(c config.ExtCommunitySet) (*ExtCommunitySet, error) {
  1256  	name := c.ExtCommunitySetName
  1257  	if name == "" {
  1258  		if len(c.ExtCommunityList) == 0 {
  1259  			return nil, nil
  1260  		}
  1261  		return nil, fmt.Errorf("empty ext-community set name")
  1262  	}
  1263  	list := make([]*regexp.Regexp, 0, len(c.ExtCommunityList))
  1264  	subtypeList := make([]bgp.ExtendedCommunityAttrSubType, 0, len(c.ExtCommunityList))
  1265  	for _, x := range c.ExtCommunityList {
  1266  		subtype, exp, err := ParseExtCommunityRegexp(x)
  1267  		if err != nil {
  1268  			return nil, err
  1269  		}
  1270  		list = append(list, exp)
  1271  		subtypeList = append(subtypeList, subtype)
  1272  	}
  1273  	return &ExtCommunitySet{
  1274  		regExpSet: regExpSet{
  1275  			typ:  DEFINED_TYPE_EXT_COMMUNITY,
  1276  			name: name,
  1277  			list: list,
  1278  		},
  1279  		subtypeList: subtypeList,
  1280  	}, nil
  1281  }
  1282  
  1283  func (s *ExtCommunitySet) Append(arg DefinedSet) error {
  1284  	err := s.regExpSet.Append(arg)
  1285  	if err != nil {
  1286  		return err
  1287  	}
  1288  	sList := arg.(*ExtCommunitySet).subtypeList
  1289  	s.subtypeList = append(s.subtypeList, sList...)
  1290  	return nil
  1291  }
  1292  
  1293  type LargeCommunitySet struct {
  1294  	regExpSet
  1295  }
  1296  
  1297  func (s *LargeCommunitySet) List() []string {
  1298  	list := make([]string, 0, len(s.list))
  1299  	for _, exp := range s.list {
  1300  		list = append(list, exp.String())
  1301  	}
  1302  	return list
  1303  }
  1304  
  1305  func (s *LargeCommunitySet) ToConfig() *config.LargeCommunitySet {
  1306  	return &config.LargeCommunitySet{
  1307  		LargeCommunitySetName: s.name,
  1308  		LargeCommunityList:    s.List(),
  1309  	}
  1310  }
  1311  
  1312  func (s *LargeCommunitySet) String() string {
  1313  	return strings.Join(s.List(), "\n")
  1314  }
  1315  
  1316  func (s *LargeCommunitySet) MarshalJSON() ([]byte, error) {
  1317  	return json.Marshal(s.ToConfig())
  1318  }
  1319  
  1320  var _regexpCommunityLarge = regexp.MustCompile(`\d+:\d+:\d+`)
  1321  
  1322  func ParseLargeCommunityRegexp(arg string) (*regexp.Regexp, error) {
  1323  	if _regexpCommunityLarge.MatchString(arg) {
  1324  		return regexp.Compile(fmt.Sprintf("^%s$", arg))
  1325  	}
  1326  	exp, err := regexp.Compile(arg)
  1327  	if err != nil {
  1328  		return nil, fmt.Errorf("invalid large-community format: %v", err)
  1329  	}
  1330  
  1331  	return exp, nil
  1332  }
  1333  
  1334  func NewLargeCommunitySet(c config.LargeCommunitySet) (*LargeCommunitySet, error) {
  1335  	name := c.LargeCommunitySetName
  1336  	if name == "" {
  1337  		if len(c.LargeCommunityList) == 0 {
  1338  			return nil, nil
  1339  		}
  1340  		return nil, fmt.Errorf("empty large community set name")
  1341  	}
  1342  	list := make([]*regexp.Regexp, 0, len(c.LargeCommunityList))
  1343  	for _, x := range c.LargeCommunityList {
  1344  		exp, err := ParseLargeCommunityRegexp(x)
  1345  		if err != nil {
  1346  			return nil, err
  1347  		}
  1348  		list = append(list, exp)
  1349  	}
  1350  	return &LargeCommunitySet{
  1351  		regExpSet: regExpSet{
  1352  			typ:  DEFINED_TYPE_LARGE_COMMUNITY,
  1353  			name: name,
  1354  			list: list,
  1355  		},
  1356  	}, nil
  1357  }
  1358  
  1359  type Condition interface {
  1360  	Name() string
  1361  	Type() ConditionType
  1362  	Evaluate(*Path, *PolicyOptions) bool
  1363  	Set() DefinedSet
  1364  }
  1365  
  1366  type NextHopCondition struct {
  1367  	set *NextHopSet
  1368  }
  1369  
  1370  func (c *NextHopCondition) Type() ConditionType {
  1371  	return CONDITION_NEXT_HOP
  1372  }
  1373  
  1374  func (c *NextHopCondition) Set() DefinedSet {
  1375  	return c.set
  1376  }
  1377  
  1378  func (c *NextHopCondition) Name() string { return "" }
  1379  
  1380  func (c *NextHopCondition) String() string {
  1381  	return c.set.String()
  1382  }
  1383  
  1384  // compare next-hop ipaddress of this condition and source address of path
  1385  // and, subsequent comparisons are skipped if that matches the conditions.
  1386  // If NextHopSet's length is zero, return true.
  1387  func (c *NextHopCondition) Evaluate(path *Path, options *PolicyOptions) bool {
  1388  	if len(c.set.list) == 0 {
  1389  		log.WithFields(log.Fields{
  1390  			"Topic": "Policy",
  1391  		}).Debug("NextHop doesn't have elements")
  1392  		return true
  1393  	}
  1394  
  1395  	nexthop := path.GetNexthop()
  1396  
  1397  	// In cases where we advertise routes from iBGP to eBGP, we want to filter
  1398  	// on the "original" nexthop. The current paths' nexthop has already been
  1399  	// set and is ready to be advertised as per:
  1400  	// https://tools.ietf.org/html/rfc4271#section-5.1.3
  1401  	if options != nil && options.OldNextHop != nil &&
  1402  		!options.OldNextHop.IsUnspecified() && !options.OldNextHop.Equal(nexthop) {
  1403  		nexthop = options.OldNextHop
  1404  	}
  1405  
  1406  	if nexthop == nil {
  1407  		return false
  1408  	}
  1409  
  1410  	for _, n := range c.set.list {
  1411  		if n.Contains(nexthop) {
  1412  			return true
  1413  		}
  1414  	}
  1415  
  1416  	return false
  1417  }
  1418  
  1419  func NewNextHopCondition(c []string) (*NextHopCondition, error) {
  1420  	if len(c) == 0 {
  1421  		return nil, nil
  1422  	}
  1423  
  1424  	list, err := NewNextHopSet(c)
  1425  	if err != nil {
  1426  		return nil, nil
  1427  	}
  1428  
  1429  	return &NextHopCondition{
  1430  		set: list,
  1431  	}, nil
  1432  }
  1433  
  1434  type PrefixCondition struct {
  1435  	set    *PrefixSet
  1436  	option MatchOption
  1437  }
  1438  
  1439  func (c *PrefixCondition) Type() ConditionType {
  1440  	return CONDITION_PREFIX
  1441  }
  1442  
  1443  func (c *PrefixCondition) Set() DefinedSet {
  1444  	return c.set
  1445  }
  1446  
  1447  func (c *PrefixCondition) Option() MatchOption {
  1448  	return c.option
  1449  }
  1450  
  1451  // compare prefixes in this condition and nlri of path and
  1452  // subsequent comparison is skipped if that matches the conditions.
  1453  // If PrefixList's length is zero, return true.
  1454  func (c *PrefixCondition) Evaluate(path *Path, _ *PolicyOptions) bool {
  1455  	var key string
  1456  	var masklen uint8
  1457  	keyf := func(ip net.IP, ones int) string {
  1458  		var buffer bytes.Buffer
  1459  		for i := 0; i < len(ip) && i < ones; i++ {
  1460  			buffer.WriteString(fmt.Sprintf("%08b", ip[i]))
  1461  		}
  1462  		return buffer.String()[:ones]
  1463  	}
  1464  	family := path.GetRouteFamily()
  1465  	switch family {
  1466  	case bgp.RF_IPv4_UC:
  1467  		masklen = path.GetNlri().(*bgp.IPAddrPrefix).Length
  1468  		key = keyf(path.GetNlri().(*bgp.IPAddrPrefix).Prefix, int(masklen))
  1469  	case bgp.RF_IPv6_UC:
  1470  		masklen = path.GetNlri().(*bgp.IPv6AddrPrefix).Length
  1471  		key = keyf(path.GetNlri().(*bgp.IPv6AddrPrefix).Prefix, int(masklen))
  1472  	default:
  1473  		return false
  1474  	}
  1475  	if family != c.set.family {
  1476  		return false
  1477  	}
  1478  
  1479  	result := false
  1480  	_, ps, ok := c.set.tree.LongestPrefix(key)
  1481  	if ok {
  1482  		for _, p := range ps.([]*Prefix) {
  1483  			if p.MasklengthRangeMin <= masklen && masklen <= p.MasklengthRangeMax {
  1484  				result = true
  1485  				break
  1486  			}
  1487  		}
  1488  	}
  1489  
  1490  	if c.option == MATCH_OPTION_INVERT {
  1491  		result = !result
  1492  	}
  1493  
  1494  	return result
  1495  }
  1496  
  1497  func (c *PrefixCondition) Name() string { return c.set.name }
  1498  
  1499  func NewPrefixCondition(c config.MatchPrefixSet) (*PrefixCondition, error) {
  1500  	if c.PrefixSet == "" {
  1501  		return nil, nil
  1502  	}
  1503  	o, err := NewMatchOption(c.MatchSetOptions)
  1504  	if err != nil {
  1505  		return nil, err
  1506  	}
  1507  	return &PrefixCondition{
  1508  		set: &PrefixSet{
  1509  			name: c.PrefixSet,
  1510  		},
  1511  		option: o,
  1512  	}, nil
  1513  }
  1514  
  1515  type NeighborCondition struct {
  1516  	set    *NeighborSet
  1517  	option MatchOption
  1518  }
  1519  
  1520  func (c *NeighborCondition) Type() ConditionType {
  1521  	return CONDITION_NEIGHBOR
  1522  }
  1523  
  1524  func (c *NeighborCondition) Set() DefinedSet {
  1525  	return c.set
  1526  }
  1527  
  1528  func (c *NeighborCondition) Option() MatchOption {
  1529  	return c.option
  1530  }
  1531  
  1532  // compare neighbor ipaddress of this condition and source address of path
  1533  // and, subsequent comparisons are skipped if that matches the conditions.
  1534  // If NeighborList's length is zero, return true.
  1535  func (c *NeighborCondition) Evaluate(path *Path, options *PolicyOptions) bool {
  1536  	if len(c.set.list) == 0 {
  1537  		log.WithFields(log.Fields{
  1538  			"Topic": "Policy",
  1539  		}).Debug("NeighborList doesn't have elements")
  1540  		return true
  1541  	}
  1542  
  1543  	neighbor := path.GetSource().Address
  1544  	if options != nil && options.Info != nil && options.Info.Address != nil {
  1545  		neighbor = options.Info.Address
  1546  	}
  1547  
  1548  	if neighbor == nil {
  1549  		return false
  1550  	}
  1551  	result := false
  1552  	for _, n := range c.set.list {
  1553  		if n.Contains(neighbor) {
  1554  			result = true
  1555  			break
  1556  		}
  1557  	}
  1558  
  1559  	if c.option == MATCH_OPTION_INVERT {
  1560  		result = !result
  1561  	}
  1562  
  1563  	return result
  1564  }
  1565  
  1566  func (c *NeighborCondition) Name() string { return c.set.name }
  1567  
  1568  func NewNeighborCondition(c config.MatchNeighborSet) (*NeighborCondition, error) {
  1569  	if c.NeighborSet == "" {
  1570  		return nil, nil
  1571  	}
  1572  	o, err := NewMatchOption(c.MatchSetOptions)
  1573  	if err != nil {
  1574  		return nil, err
  1575  	}
  1576  	return &NeighborCondition{
  1577  		set: &NeighborSet{
  1578  			name: c.NeighborSet,
  1579  		},
  1580  		option: o,
  1581  	}, nil
  1582  }
  1583  
  1584  type AsPathCondition struct {
  1585  	set    *AsPathSet
  1586  	option MatchOption
  1587  }
  1588  
  1589  func (c *AsPathCondition) Type() ConditionType {
  1590  	return CONDITION_AS_PATH
  1591  }
  1592  
  1593  func (c *AsPathCondition) Set() DefinedSet {
  1594  	return c.set
  1595  }
  1596  
  1597  func (c *AsPathCondition) Option() MatchOption {
  1598  	return c.option
  1599  }
  1600  
  1601  func (c *AsPathCondition) Evaluate(path *Path, _ *PolicyOptions) bool {
  1602  	if len(c.set.singleList) > 0 {
  1603  		aspath := path.GetAsSeqList()
  1604  		for _, m := range c.set.singleList {
  1605  			result := m.Match(aspath)
  1606  			if c.option == MATCH_OPTION_ALL && !result {
  1607  				return false
  1608  			}
  1609  			if c.option == MATCH_OPTION_ANY && result {
  1610  				return true
  1611  			}
  1612  			if c.option == MATCH_OPTION_INVERT && result {
  1613  				return false
  1614  			}
  1615  		}
  1616  	}
  1617  	if len(c.set.list) > 0 {
  1618  		aspath := path.GetAsString()
  1619  		for _, r := range c.set.list {
  1620  			result := r.MatchString(aspath)
  1621  			if c.option == MATCH_OPTION_ALL && !result {
  1622  				return false
  1623  			}
  1624  			if c.option == MATCH_OPTION_ANY && result {
  1625  				return true
  1626  			}
  1627  			if c.option == MATCH_OPTION_INVERT && result {
  1628  				return false
  1629  			}
  1630  		}
  1631  	}
  1632  	if c.option == MATCH_OPTION_ANY {
  1633  		return false
  1634  	}
  1635  	return true
  1636  }
  1637  
  1638  func (c *AsPathCondition) Name() string { return c.set.name }
  1639  
  1640  func NewAsPathCondition(c config.MatchAsPathSet) (*AsPathCondition, error) {
  1641  	if c.AsPathSet == "" {
  1642  		return nil, nil
  1643  	}
  1644  	o, err := NewMatchOption(c.MatchSetOptions)
  1645  	if err != nil {
  1646  		return nil, err
  1647  	}
  1648  	return &AsPathCondition{
  1649  		set: &AsPathSet{
  1650  			name: c.AsPathSet,
  1651  		},
  1652  		option: o,
  1653  	}, nil
  1654  }
  1655  
  1656  type CommunityCondition struct {
  1657  	set    *CommunitySet
  1658  	option MatchOption
  1659  }
  1660  
  1661  func (c *CommunityCondition) Type() ConditionType {
  1662  	return CONDITION_COMMUNITY
  1663  }
  1664  
  1665  func (c *CommunityCondition) Set() DefinedSet {
  1666  	return c.set
  1667  }
  1668  
  1669  func (c *CommunityCondition) Option() MatchOption {
  1670  	return c.option
  1671  }
  1672  
  1673  func (c *CommunityCondition) Evaluate(path *Path, _ *PolicyOptions) bool {
  1674  	cs := path.GetCommunities()
  1675  	result := false
  1676  	for _, x := range c.set.list {
  1677  		result = false
  1678  		for _, y := range cs {
  1679  			if x.MatchString(fmt.Sprintf("%d:%d", y>>16, y&0x0000ffff)) {
  1680  				result = true
  1681  				break
  1682  			}
  1683  		}
  1684  		if c.option == MATCH_OPTION_ALL && !result {
  1685  			break
  1686  		}
  1687  		if (c.option == MATCH_OPTION_ANY || c.option == MATCH_OPTION_INVERT) && result {
  1688  			break
  1689  		}
  1690  	}
  1691  	if c.option == MATCH_OPTION_INVERT {
  1692  		result = !result
  1693  	}
  1694  	return result
  1695  }
  1696  
  1697  func (c *CommunityCondition) Name() string { return c.set.name }
  1698  
  1699  func NewCommunityCondition(c config.MatchCommunitySet) (*CommunityCondition, error) {
  1700  	if c.CommunitySet == "" {
  1701  		return nil, nil
  1702  	}
  1703  	o, err := NewMatchOption(c.MatchSetOptions)
  1704  	if err != nil {
  1705  		return nil, err
  1706  	}
  1707  	return &CommunityCondition{
  1708  		set: &CommunitySet{
  1709  			regExpSet: regExpSet{
  1710  				name: c.CommunitySet,
  1711  			},
  1712  		},
  1713  		option: o,
  1714  	}, nil
  1715  }
  1716  
  1717  type ExtCommunityCondition struct {
  1718  	set    *ExtCommunitySet
  1719  	option MatchOption
  1720  }
  1721  
  1722  func (c *ExtCommunityCondition) Type() ConditionType {
  1723  	return CONDITION_EXT_COMMUNITY
  1724  }
  1725  
  1726  func (c *ExtCommunityCondition) Set() DefinedSet {
  1727  	return c.set
  1728  }
  1729  
  1730  func (c *ExtCommunityCondition) Option() MatchOption {
  1731  	return c.option
  1732  }
  1733  
  1734  func (c *ExtCommunityCondition) Evaluate(path *Path, _ *PolicyOptions) bool {
  1735  	es := path.GetExtCommunities()
  1736  	result := false
  1737  	for _, x := range es {
  1738  		result = false
  1739  		typ, subtype := x.GetTypes()
  1740  		// match only with transitive community. see RFC7153
  1741  		if typ >= 0x3f {
  1742  			continue
  1743  		}
  1744  		for idx, y := range c.set.list {
  1745  			if subtype == c.set.subtypeList[idx] && y.MatchString(x.String()) {
  1746  				result = true
  1747  				break
  1748  			}
  1749  		}
  1750  		if c.option == MATCH_OPTION_ALL && !result {
  1751  			break
  1752  		}
  1753  		if c.option == MATCH_OPTION_ANY && result {
  1754  			break
  1755  		}
  1756  	}
  1757  	if c.option == MATCH_OPTION_INVERT {
  1758  		result = !result
  1759  	}
  1760  	return result
  1761  }
  1762  
  1763  func (c *ExtCommunityCondition) Name() string { return c.set.name }
  1764  
  1765  func NewExtCommunityCondition(c config.MatchExtCommunitySet) (*ExtCommunityCondition, error) {
  1766  	if c.ExtCommunitySet == "" {
  1767  		return nil, nil
  1768  	}
  1769  	o, err := NewMatchOption(c.MatchSetOptions)
  1770  	if err != nil {
  1771  		return nil, err
  1772  	}
  1773  	return &ExtCommunityCondition{
  1774  		set: &ExtCommunitySet{
  1775  			regExpSet: regExpSet{
  1776  				name: c.ExtCommunitySet,
  1777  			},
  1778  		},
  1779  		option: o,
  1780  	}, nil
  1781  }
  1782  
  1783  type LargeCommunityCondition struct {
  1784  	set    *LargeCommunitySet
  1785  	option MatchOption
  1786  }
  1787  
  1788  func (c *LargeCommunityCondition) Type() ConditionType {
  1789  	return CONDITION_LARGE_COMMUNITY
  1790  }
  1791  
  1792  func (c *LargeCommunityCondition) Set() DefinedSet {
  1793  	return c.set
  1794  }
  1795  
  1796  func (c *LargeCommunityCondition) Option() MatchOption {
  1797  	return c.option
  1798  }
  1799  
  1800  func (c *LargeCommunityCondition) Evaluate(path *Path, _ *PolicyOptions) bool {
  1801  	result := false
  1802  	cs := path.GetLargeCommunities()
  1803  	for _, x := range c.set.list {
  1804  		result = false
  1805  		for _, y := range cs {
  1806  			if x.MatchString(y.String()) {
  1807  				result = true
  1808  				break
  1809  			}
  1810  		}
  1811  		if c.option == MATCH_OPTION_ALL && !result {
  1812  			break
  1813  		}
  1814  		if (c.option == MATCH_OPTION_ANY || c.option == MATCH_OPTION_INVERT) && result {
  1815  			break
  1816  		}
  1817  	}
  1818  	if c.option == MATCH_OPTION_INVERT {
  1819  		result = !result
  1820  	}
  1821  	return result
  1822  }
  1823  
  1824  func (c *LargeCommunityCondition) Name() string { return c.set.name }
  1825  
  1826  func NewLargeCommunityCondition(c config.MatchLargeCommunitySet) (*LargeCommunityCondition, error) {
  1827  	if c.LargeCommunitySet == "" {
  1828  		return nil, nil
  1829  	}
  1830  	o, err := NewMatchOption(c.MatchSetOptions)
  1831  	if err != nil {
  1832  		return nil, err
  1833  	}
  1834  	return &LargeCommunityCondition{
  1835  		set: &LargeCommunitySet{
  1836  			regExpSet: regExpSet{
  1837  				name: c.LargeCommunitySet,
  1838  			},
  1839  		},
  1840  		option: o,
  1841  	}, nil
  1842  }
  1843  
  1844  type AsPathLengthCondition struct {
  1845  	length   uint32
  1846  	operator AttributeComparison
  1847  }
  1848  
  1849  func (c *AsPathLengthCondition) Type() ConditionType {
  1850  	return CONDITION_AS_PATH_LENGTH
  1851  }
  1852  
  1853  // compare AS_PATH length in the message's AS_PATH attribute with
  1854  // the one in condition.
  1855  func (c *AsPathLengthCondition) Evaluate(path *Path, _ *PolicyOptions) bool {
  1856  
  1857  	length := uint32(path.GetAsPathLen())
  1858  	result := false
  1859  	switch c.operator {
  1860  	case ATTRIBUTE_EQ:
  1861  		result = c.length == length
  1862  	case ATTRIBUTE_GE:
  1863  		result = c.length <= length
  1864  	case ATTRIBUTE_LE:
  1865  		result = c.length >= length
  1866  	}
  1867  
  1868  	return result
  1869  }
  1870  
  1871  func (c *AsPathLengthCondition) Set() DefinedSet {
  1872  	return nil
  1873  }
  1874  
  1875  func (c *AsPathLengthCondition) Name() string { return "" }
  1876  
  1877  func (c *AsPathLengthCondition) String() string {
  1878  	return fmt.Sprintf("%s%d", c.operator, c.length)
  1879  }
  1880  
  1881  func NewAsPathLengthCondition(c config.AsPathLength) (*AsPathLengthCondition, error) {
  1882  	if c.Value == 0 && c.Operator == "" {
  1883  		return nil, nil
  1884  	}
  1885  	var op AttributeComparison
  1886  	if i := c.Operator.ToInt(); i < 0 {
  1887  		return nil, fmt.Errorf("invalid as path length operator: %s", c.Operator)
  1888  	} else {
  1889  		// take mod 3 because we have extended openconfig attribute-comparison
  1890  		// for simple configuration. see config.AttributeComparison definition
  1891  		op = AttributeComparison(i % 3)
  1892  	}
  1893  	return &AsPathLengthCondition{
  1894  		length:   c.Value,
  1895  		operator: op,
  1896  	}, nil
  1897  }
  1898  
  1899  type RpkiValidationCondition struct {
  1900  	result config.RpkiValidationResultType
  1901  }
  1902  
  1903  func (c *RpkiValidationCondition) Type() ConditionType {
  1904  	return CONDITION_RPKI
  1905  }
  1906  
  1907  func (c *RpkiValidationCondition) Evaluate(path *Path, options *PolicyOptions) bool {
  1908  	if options != nil && options.ValidationResult != nil {
  1909  		return c.result == options.ValidationResult.Status
  1910  	}
  1911  	return false
  1912  }
  1913  
  1914  func (c *RpkiValidationCondition) Set() DefinedSet {
  1915  	return nil
  1916  }
  1917  
  1918  func (c *RpkiValidationCondition) Name() string { return "" }
  1919  
  1920  func (c *RpkiValidationCondition) String() string {
  1921  	return string(c.result)
  1922  }
  1923  
  1924  func NewRpkiValidationCondition(c config.RpkiValidationResultType) (*RpkiValidationCondition, error) {
  1925  	if c == config.RpkiValidationResultType("") || c == config.RPKI_VALIDATION_RESULT_TYPE_NONE {
  1926  		return nil, nil
  1927  	}
  1928  	return &RpkiValidationCondition{
  1929  		result: c,
  1930  	}, nil
  1931  }
  1932  
  1933  type RouteTypeCondition struct {
  1934  	typ config.RouteType
  1935  }
  1936  
  1937  func (c *RouteTypeCondition) Type() ConditionType {
  1938  	return CONDITION_ROUTE_TYPE
  1939  }
  1940  
  1941  func (c *RouteTypeCondition) Evaluate(path *Path, _ *PolicyOptions) bool {
  1942  	switch c.typ {
  1943  	case config.ROUTE_TYPE_LOCAL:
  1944  		return path.IsLocal()
  1945  	case config.ROUTE_TYPE_INTERNAL:
  1946  		return !path.IsLocal() && path.IsIBGP()
  1947  	case config.ROUTE_TYPE_EXTERNAL:
  1948  		return !path.IsLocal() && !path.IsIBGP()
  1949  	}
  1950  	return false
  1951  }
  1952  
  1953  func (c *RouteTypeCondition) Set() DefinedSet {
  1954  	return nil
  1955  }
  1956  
  1957  func (c *RouteTypeCondition) Name() string { return "" }
  1958  
  1959  func (c *RouteTypeCondition) String() string {
  1960  	return string(c.typ)
  1961  }
  1962  
  1963  func NewRouteTypeCondition(c config.RouteType) (*RouteTypeCondition, error) {
  1964  	if string(c) == "" || c == config.ROUTE_TYPE_NONE {
  1965  		return nil, nil
  1966  	}
  1967  	if err := c.Validate(); err != nil {
  1968  		return nil, err
  1969  	}
  1970  	return &RouteTypeCondition{
  1971  		typ: c,
  1972  	}, nil
  1973  }
  1974  
  1975  type AfiSafiInCondition struct {
  1976  	routeFamilies []bgp.RouteFamily
  1977  }
  1978  
  1979  func (c *AfiSafiInCondition) Type() ConditionType {
  1980  	return CONDITION_AFI_SAFI_IN
  1981  }
  1982  
  1983  func (c *AfiSafiInCondition) Evaluate(path *Path, _ *PolicyOptions) bool {
  1984  	for _, rf := range c.routeFamilies {
  1985  		if path.GetRouteFamily() == rf {
  1986  			return true
  1987  		}
  1988  	}
  1989  	return false
  1990  }
  1991  
  1992  func (c *AfiSafiInCondition) Set() DefinedSet {
  1993  	return nil
  1994  }
  1995  
  1996  func (c *AfiSafiInCondition) Name() string { return "" }
  1997  
  1998  func (c *AfiSafiInCondition) String() string {
  1999  	tmp := make([]string, 0, len(c.routeFamilies))
  2000  	for _, afiSafi := range c.routeFamilies {
  2001  		tmp = append(tmp, afiSafi.String())
  2002  	}
  2003  	return strings.Join(tmp, " ")
  2004  }
  2005  
  2006  func NewAfiSafiInCondition(afiSafInConfig []config.AfiSafiType) (*AfiSafiInCondition, error) {
  2007  	if afiSafInConfig == nil {
  2008  		return nil, nil
  2009  	}
  2010  
  2011  	routeFamilies := make([]bgp.RouteFamily, 0, len(afiSafInConfig))
  2012  	for _, afiSafiValue := range afiSafInConfig {
  2013  		if err := afiSafiValue.Validate(); err != nil {
  2014  			return nil, err
  2015  		}
  2016  		rf, err := bgp.GetRouteFamily(string(afiSafiValue))
  2017  		if err != nil {
  2018  			return nil, err
  2019  		}
  2020  		routeFamilies = append(routeFamilies, rf)
  2021  	}
  2022  	return &AfiSafiInCondition{
  2023  		routeFamilies: routeFamilies,
  2024  	}, nil
  2025  }
  2026  
  2027  type Action interface {
  2028  	Type() ActionType
  2029  	Apply(*Path, *PolicyOptions) *Path
  2030  	String() string
  2031  }
  2032  
  2033  type RoutingAction struct {
  2034  	AcceptRoute bool
  2035  }
  2036  
  2037  func (a *RoutingAction) Type() ActionType {
  2038  	return ACTION_ROUTING
  2039  }
  2040  
  2041  func (a *RoutingAction) Apply(path *Path, _ *PolicyOptions) *Path {
  2042  	if a.AcceptRoute {
  2043  		return path
  2044  	}
  2045  	return nil
  2046  }
  2047  
  2048  func (a *RoutingAction) String() string {
  2049  	action := "reject"
  2050  	if a.AcceptRoute {
  2051  		action = "accept"
  2052  	}
  2053  	return action
  2054  }
  2055  
  2056  func NewRoutingAction(c config.RouteDisposition) (*RoutingAction, error) {
  2057  	var accept bool
  2058  	switch c {
  2059  	case config.RouteDisposition(""), config.ROUTE_DISPOSITION_NONE:
  2060  		return nil, nil
  2061  	case config.ROUTE_DISPOSITION_ACCEPT_ROUTE:
  2062  		accept = true
  2063  	case config.ROUTE_DISPOSITION_REJECT_ROUTE:
  2064  		accept = false
  2065  	default:
  2066  		return nil, fmt.Errorf("invalid route disposition")
  2067  	}
  2068  	return &RoutingAction{
  2069  		AcceptRoute: accept,
  2070  	}, nil
  2071  }
  2072  
  2073  type CommunityAction struct {
  2074  	action     config.BgpSetCommunityOptionType
  2075  	list       []uint32
  2076  	removeList []*regexp.Regexp
  2077  }
  2078  
  2079  func RegexpRemoveCommunities(path *Path, exps []*regexp.Regexp) {
  2080  	comms := path.GetCommunities()
  2081  	newComms := make([]uint32, 0, len(comms))
  2082  	for _, comm := range comms {
  2083  		c := fmt.Sprintf("%d:%d", comm>>16, comm&0x0000ffff)
  2084  		match := false
  2085  		for _, exp := range exps {
  2086  			if exp.MatchString(c) {
  2087  				match = true
  2088  				break
  2089  			}
  2090  		}
  2091  		if !match {
  2092  			newComms = append(newComms, comm)
  2093  		}
  2094  	}
  2095  	path.SetCommunities(newComms, true)
  2096  }
  2097  
  2098  func RegexpRemoveExtCommunities(path *Path, exps []*regexp.Regexp, subtypes []bgp.ExtendedCommunityAttrSubType) {
  2099  	comms := path.GetExtCommunities()
  2100  	newComms := make([]bgp.ExtendedCommunityInterface, 0, len(comms))
  2101  	for _, comm := range comms {
  2102  		match := false
  2103  		typ, subtype := comm.GetTypes()
  2104  		// match only with transitive community. see RFC7153
  2105  		if typ >= 0x3f {
  2106  			continue
  2107  		}
  2108  		for idx, exp := range exps {
  2109  			if subtype == subtypes[idx] && exp.MatchString(comm.String()) {
  2110  				match = true
  2111  				break
  2112  			}
  2113  		}
  2114  		if !match {
  2115  			newComms = append(newComms, comm)
  2116  		}
  2117  	}
  2118  	path.SetExtCommunities(newComms, true)
  2119  }
  2120  
  2121  func RegexpRemoveLargeCommunities(path *Path, exps []*regexp.Regexp) {
  2122  	comms := path.GetLargeCommunities()
  2123  	newComms := make([]*bgp.LargeCommunity, 0, len(comms))
  2124  	for _, comm := range comms {
  2125  		c := comm.String()
  2126  		match := false
  2127  		for _, exp := range exps {
  2128  			if exp.MatchString(c) {
  2129  				match = true
  2130  				break
  2131  			}
  2132  		}
  2133  		if !match {
  2134  			newComms = append(newComms, comm)
  2135  		}
  2136  	}
  2137  	path.SetLargeCommunities(newComms, true)
  2138  }
  2139  
  2140  func (a *CommunityAction) Type() ActionType {
  2141  	return ACTION_COMMUNITY
  2142  }
  2143  
  2144  func (a *CommunityAction) Apply(path *Path, _ *PolicyOptions) *Path {
  2145  	switch a.action {
  2146  	case config.BGP_SET_COMMUNITY_OPTION_TYPE_ADD:
  2147  		path.SetCommunities(a.list, false)
  2148  	case config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE:
  2149  		RegexpRemoveCommunities(path, a.removeList)
  2150  	case config.BGP_SET_COMMUNITY_OPTION_TYPE_REPLACE:
  2151  		path.SetCommunities(a.list, true)
  2152  	}
  2153  	return path
  2154  }
  2155  
  2156  func (a *CommunityAction) ToConfig() *config.SetCommunity {
  2157  	cs := make([]string, 0, len(a.list)+len(a.removeList))
  2158  	for _, comm := range a.list {
  2159  		c := fmt.Sprintf("%d:%d", comm>>16, comm&0x0000ffff)
  2160  		cs = append(cs, c)
  2161  	}
  2162  	for _, exp := range a.removeList {
  2163  		cs = append(cs, exp.String())
  2164  	}
  2165  	return &config.SetCommunity{
  2166  		Options:            string(a.action),
  2167  		SetCommunityMethod: config.SetCommunityMethod{CommunitiesList: cs},
  2168  	}
  2169  }
  2170  
  2171  func (a *CommunityAction) MarshalJSON() ([]byte, error) {
  2172  	return json.Marshal(a.ToConfig())
  2173  }
  2174  
  2175  // TODO: this is not efficient use of regexp, probably slow
  2176  var _regexpCommunityReplaceString = regexp.MustCompile(`[\^\$]`)
  2177  
  2178  func (a *CommunityAction) String() string {
  2179  	list := a.ToConfig().SetCommunityMethod.CommunitiesList
  2180  	l := _regexpCommunityReplaceString.ReplaceAllString(strings.Join(list, ", "), "")
  2181  	return fmt.Sprintf("%s[%s]", a.action, l)
  2182  }
  2183  
  2184  func NewCommunityAction(c config.SetCommunity) (*CommunityAction, error) {
  2185  	a, ok := CommunityOptionValueMap[strings.ToLower(c.Options)]
  2186  	if !ok {
  2187  		if len(c.SetCommunityMethod.CommunitiesList) == 0 {
  2188  			return nil, nil
  2189  		}
  2190  		return nil, fmt.Errorf("invalid option name: %s", c.Options)
  2191  	}
  2192  	var list []uint32
  2193  	var removeList []*regexp.Regexp
  2194  	if a == config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE {
  2195  		removeList = make([]*regexp.Regexp, 0, len(c.SetCommunityMethod.CommunitiesList))
  2196  	} else {
  2197  		list = make([]uint32, 0, len(c.SetCommunityMethod.CommunitiesList))
  2198  	}
  2199  	for _, x := range c.SetCommunityMethod.CommunitiesList {
  2200  		if a == config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE {
  2201  			exp, err := ParseCommunityRegexp(x)
  2202  			if err != nil {
  2203  				return nil, err
  2204  			}
  2205  			removeList = append(removeList, exp)
  2206  		} else {
  2207  			comm, err := ParseCommunity(x)
  2208  			if err != nil {
  2209  				return nil, err
  2210  			}
  2211  			list = append(list, comm)
  2212  		}
  2213  	}
  2214  	return &CommunityAction{
  2215  		action:     a,
  2216  		list:       list,
  2217  		removeList: removeList,
  2218  	}, nil
  2219  }
  2220  
  2221  type ExtCommunityAction struct {
  2222  	action      config.BgpSetCommunityOptionType
  2223  	list        []bgp.ExtendedCommunityInterface
  2224  	removeList  []*regexp.Regexp
  2225  	subtypeList []bgp.ExtendedCommunityAttrSubType
  2226  }
  2227  
  2228  func (a *ExtCommunityAction) Type() ActionType {
  2229  	return ACTION_EXT_COMMUNITY
  2230  }
  2231  
  2232  func (a *ExtCommunityAction) Apply(path *Path, _ *PolicyOptions) *Path {
  2233  	switch a.action {
  2234  	case config.BGP_SET_COMMUNITY_OPTION_TYPE_ADD:
  2235  		path.SetExtCommunities(a.list, false)
  2236  	case config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE:
  2237  		RegexpRemoveExtCommunities(path, a.removeList, a.subtypeList)
  2238  	case config.BGP_SET_COMMUNITY_OPTION_TYPE_REPLACE:
  2239  		path.SetExtCommunities(a.list, true)
  2240  	}
  2241  	return path
  2242  }
  2243  
  2244  func (a *ExtCommunityAction) ToConfig() *config.SetExtCommunity {
  2245  	cs := make([]string, 0, len(a.list)+len(a.removeList))
  2246  	f := func(idx int, arg string) string {
  2247  		switch a.subtypeList[idx] {
  2248  		case bgp.EC_SUBTYPE_ROUTE_TARGET:
  2249  			return fmt.Sprintf("rt:%s", arg)
  2250  		case bgp.EC_SUBTYPE_ROUTE_ORIGIN:
  2251  			return fmt.Sprintf("soo:%s", arg)
  2252  		case bgp.EC_SUBTYPE_ORIGIN_VALIDATION:
  2253  			return arg
  2254  		default:
  2255  			return fmt.Sprintf("%d:%s", a.subtypeList[idx], arg)
  2256  		}
  2257  	}
  2258  	for idx, c := range a.list {
  2259  		cs = append(cs, f(idx, c.String()))
  2260  	}
  2261  	for idx, exp := range a.removeList {
  2262  		cs = append(cs, f(idx, exp.String()))
  2263  	}
  2264  	return &config.SetExtCommunity{
  2265  		Options: string(a.action),
  2266  		SetExtCommunityMethod: config.SetExtCommunityMethod{
  2267  			CommunitiesList: cs,
  2268  		},
  2269  	}
  2270  }
  2271  
  2272  func (a *ExtCommunityAction) String() string {
  2273  	list := a.ToConfig().SetExtCommunityMethod.CommunitiesList
  2274  	l := _regexpCommunityReplaceString.ReplaceAllString(strings.Join(list, ", "), "")
  2275  	return fmt.Sprintf("%s[%s]", a.action, l)
  2276  }
  2277  
  2278  func (a *ExtCommunityAction) MarshalJSON() ([]byte, error) {
  2279  	return json.Marshal(a.ToConfig())
  2280  }
  2281  
  2282  func NewExtCommunityAction(c config.SetExtCommunity) (*ExtCommunityAction, error) {
  2283  	a, ok := CommunityOptionValueMap[strings.ToLower(c.Options)]
  2284  	if !ok {
  2285  		if len(c.SetExtCommunityMethod.CommunitiesList) == 0 {
  2286  			return nil, nil
  2287  		}
  2288  		return nil, fmt.Errorf("invalid option name: %s", c.Options)
  2289  	}
  2290  	var list []bgp.ExtendedCommunityInterface
  2291  	var removeList []*regexp.Regexp
  2292  	subtypeList := make([]bgp.ExtendedCommunityAttrSubType, 0, len(c.SetExtCommunityMethod.CommunitiesList))
  2293  	if a == config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE {
  2294  		removeList = make([]*regexp.Regexp, 0, len(c.SetExtCommunityMethod.CommunitiesList))
  2295  	} else {
  2296  		list = make([]bgp.ExtendedCommunityInterface, 0, len(c.SetExtCommunityMethod.CommunitiesList))
  2297  	}
  2298  	for _, x := range c.SetExtCommunityMethod.CommunitiesList {
  2299  		if a == config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE {
  2300  			subtype, exp, err := ParseExtCommunityRegexp(x)
  2301  			if err != nil {
  2302  				return nil, err
  2303  			}
  2304  			removeList = append(removeList, exp)
  2305  			subtypeList = append(subtypeList, subtype)
  2306  		} else {
  2307  			comm, err := ParseExtCommunity(x)
  2308  			if err != nil {
  2309  				return nil, err
  2310  			}
  2311  			list = append(list, comm)
  2312  			_, subtype := comm.GetTypes()
  2313  			subtypeList = append(subtypeList, subtype)
  2314  		}
  2315  	}
  2316  	return &ExtCommunityAction{
  2317  		action:      a,
  2318  		list:        list,
  2319  		removeList:  removeList,
  2320  		subtypeList: subtypeList,
  2321  	}, nil
  2322  }
  2323  
  2324  type LargeCommunityAction struct {
  2325  	action     config.BgpSetCommunityOptionType
  2326  	list       []*bgp.LargeCommunity
  2327  	removeList []*regexp.Regexp
  2328  }
  2329  
  2330  func (a *LargeCommunityAction) Type() ActionType {
  2331  	return ACTION_LARGE_COMMUNITY
  2332  }
  2333  
  2334  func (a *LargeCommunityAction) Apply(path *Path, _ *PolicyOptions) *Path {
  2335  	switch a.action {
  2336  	case config.BGP_SET_COMMUNITY_OPTION_TYPE_ADD:
  2337  		path.SetLargeCommunities(a.list, false)
  2338  	case config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE:
  2339  		RegexpRemoveLargeCommunities(path, a.removeList)
  2340  	case config.BGP_SET_COMMUNITY_OPTION_TYPE_REPLACE:
  2341  		path.SetLargeCommunities(a.list, true)
  2342  	}
  2343  	return path
  2344  }
  2345  
  2346  func (a *LargeCommunityAction) ToConfig() *config.SetLargeCommunity {
  2347  	cs := make([]string, 0, len(a.list)+len(a.removeList))
  2348  	for _, comm := range a.list {
  2349  		cs = append(cs, comm.String())
  2350  	}
  2351  	for _, exp := range a.removeList {
  2352  		cs = append(cs, exp.String())
  2353  	}
  2354  	return &config.SetLargeCommunity{
  2355  		SetLargeCommunityMethod: config.SetLargeCommunityMethod{CommunitiesList: cs},
  2356  		Options:                 config.BgpSetCommunityOptionType(a.action),
  2357  	}
  2358  }
  2359  
  2360  func (a *LargeCommunityAction) String() string {
  2361  	list := a.ToConfig().SetLargeCommunityMethod.CommunitiesList
  2362  	l := _regexpCommunityReplaceString.ReplaceAllString(strings.Join(list, ", "), "")
  2363  	return fmt.Sprintf("%s[%s]", a.action, l)
  2364  }
  2365  
  2366  func (a *LargeCommunityAction) MarshalJSON() ([]byte, error) {
  2367  	return json.Marshal(a.ToConfig())
  2368  }
  2369  
  2370  func NewLargeCommunityAction(c config.SetLargeCommunity) (*LargeCommunityAction, error) {
  2371  	a, ok := CommunityOptionValueMap[strings.ToLower(string(c.Options))]
  2372  	if !ok {
  2373  		if len(c.SetLargeCommunityMethod.CommunitiesList) == 0 {
  2374  			return nil, nil
  2375  		}
  2376  		return nil, fmt.Errorf("invalid option name: %s", c.Options)
  2377  	}
  2378  	var list []*bgp.LargeCommunity
  2379  	var removeList []*regexp.Regexp
  2380  	if a == config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE {
  2381  		removeList = make([]*regexp.Regexp, 0, len(c.SetLargeCommunityMethod.CommunitiesList))
  2382  	} else {
  2383  		list = make([]*bgp.LargeCommunity, 0, len(c.SetLargeCommunityMethod.CommunitiesList))
  2384  	}
  2385  	for _, x := range c.SetLargeCommunityMethod.CommunitiesList {
  2386  		if a == config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE {
  2387  			exp, err := ParseLargeCommunityRegexp(x)
  2388  			if err != nil {
  2389  				return nil, err
  2390  			}
  2391  			removeList = append(removeList, exp)
  2392  		} else {
  2393  			comm, err := bgp.ParseLargeCommunity(x)
  2394  			if err != nil {
  2395  				return nil, err
  2396  			}
  2397  			list = append(list, comm)
  2398  		}
  2399  	}
  2400  	return &LargeCommunityAction{
  2401  		action:     a,
  2402  		list:       list,
  2403  		removeList: removeList,
  2404  	}, nil
  2405  
  2406  }
  2407  
  2408  type MedAction struct {
  2409  	value  int64
  2410  	action MedActionType
  2411  }
  2412  
  2413  func (a *MedAction) Type() ActionType {
  2414  	return ACTION_MED
  2415  }
  2416  
  2417  func (a *MedAction) Apply(path *Path, _ *PolicyOptions) *Path {
  2418  	var err error
  2419  	switch a.action {
  2420  	case MED_ACTION_MOD:
  2421  		err = path.SetMed(a.value, false)
  2422  	case MED_ACTION_REPLACE:
  2423  		err = path.SetMed(a.value, true)
  2424  	}
  2425  
  2426  	if err != nil {
  2427  		log.WithFields(log.Fields{
  2428  			"Topic": "Policy",
  2429  			"Type":  "Med Action",
  2430  			"Error": err,
  2431  		}).Warn("Could not set Med on path")
  2432  	}
  2433  	return path
  2434  }
  2435  
  2436  func (a *MedAction) ToConfig() config.BgpSetMedType {
  2437  	if a.action == MED_ACTION_MOD && a.value > 0 {
  2438  		return config.BgpSetMedType(fmt.Sprintf("+%d", a.value))
  2439  	}
  2440  	return config.BgpSetMedType(fmt.Sprintf("%d", a.value))
  2441  }
  2442  
  2443  func (a *MedAction) String() string {
  2444  	return string(a.ToConfig())
  2445  }
  2446  
  2447  func (a *MedAction) MarshalJSON() ([]byte, error) {
  2448  	return json.Marshal(a.ToConfig())
  2449  }
  2450  
  2451  var _regexpParseMedAction = regexp.MustCompile(`^(\+|\-)?(\d+)$`)
  2452  
  2453  func NewMedAction(c config.BgpSetMedType) (*MedAction, error) {
  2454  	if string(c) == "" {
  2455  		return nil, nil
  2456  	}
  2457  
  2458  	elems := _regexpParseMedAction.FindStringSubmatch(string(c))
  2459  	if len(elems) != 3 {
  2460  		return nil, fmt.Errorf("invalid med action format")
  2461  	}
  2462  	action := MED_ACTION_REPLACE
  2463  	switch elems[1] {
  2464  	case "+", "-":
  2465  		action = MED_ACTION_MOD
  2466  	}
  2467  	value, _ := strconv.ParseInt(string(c), 10, 64)
  2468  	return &MedAction{
  2469  		value:  value,
  2470  		action: action,
  2471  	}, nil
  2472  }
  2473  
  2474  func NewMedActionFromApiStruct(action MedActionType, value int64) *MedAction {
  2475  	return &MedAction{action: action, value: value}
  2476  }
  2477  
  2478  type LocalPrefAction struct {
  2479  	value uint32
  2480  }
  2481  
  2482  func (a *LocalPrefAction) Type() ActionType {
  2483  	return ACTION_LOCAL_PREF
  2484  }
  2485  
  2486  func (a *LocalPrefAction) Apply(path *Path, _ *PolicyOptions) *Path {
  2487  	path.setPathAttr(bgp.NewPathAttributeLocalPref(a.value))
  2488  	return path
  2489  }
  2490  
  2491  func (a *LocalPrefAction) ToConfig() uint32 {
  2492  	return a.value
  2493  }
  2494  
  2495  func (a *LocalPrefAction) String() string {
  2496  	return fmt.Sprintf("%d", a.value)
  2497  }
  2498  
  2499  func (a *LocalPrefAction) MarshalJSON() ([]byte, error) {
  2500  	return json.Marshal(a.ToConfig())
  2501  }
  2502  
  2503  func NewLocalPrefAction(value uint32) (*LocalPrefAction, error) {
  2504  	if value == 0 {
  2505  		return nil, nil
  2506  	}
  2507  	return &LocalPrefAction{
  2508  		value: value,
  2509  	}, nil
  2510  }
  2511  
  2512  type AsPathPrependAction struct {
  2513  	asn         uint32
  2514  	useLeftMost bool
  2515  	repeat      uint8
  2516  }
  2517  
  2518  func (a *AsPathPrependAction) Type() ActionType {
  2519  	return ACTION_AS_PATH_PREPEND
  2520  }
  2521  
  2522  func (a *AsPathPrependAction) Apply(path *Path, option *PolicyOptions) *Path {
  2523  	var asn uint32
  2524  	if a.useLeftMost {
  2525  		aspath := path.GetAsSeqList()
  2526  		if len(aspath) == 0 {
  2527  			log.WithFields(log.Fields{
  2528  				"Topic": "Policy",
  2529  				"Type":  "AsPathPrepend Action",
  2530  			}).Warn("aspath length is zero.")
  2531  			return path
  2532  		}
  2533  		asn = aspath[0]
  2534  		if asn == 0 {
  2535  			log.WithFields(log.Fields{
  2536  				"Topic": "Policy",
  2537  				"Type":  "AsPathPrepend Action",
  2538  			}).Warn("left-most ASN is not seq")
  2539  			return path
  2540  		}
  2541  	} else {
  2542  		asn = a.asn
  2543  	}
  2544  
  2545  	confed := option != nil && option.Info != nil && option.Info.Confederation
  2546  	path.PrependAsn(asn, a.repeat, confed)
  2547  
  2548  	return path
  2549  }
  2550  
  2551  func (a *AsPathPrependAction) ToConfig() *config.SetAsPathPrepend {
  2552  	return &config.SetAsPathPrepend{
  2553  		RepeatN: uint8(a.repeat),
  2554  		As: func() string {
  2555  			if a.useLeftMost {
  2556  				return "last-as"
  2557  			}
  2558  			return fmt.Sprintf("%d", a.asn)
  2559  		}(),
  2560  	}
  2561  }
  2562  
  2563  func (a *AsPathPrependAction) String() string {
  2564  	c := a.ToConfig()
  2565  	return fmt.Sprintf("prepend %s %d times", c.As, c.RepeatN)
  2566  }
  2567  
  2568  func (a *AsPathPrependAction) MarshalJSON() ([]byte, error) {
  2569  	return json.Marshal(a.ToConfig())
  2570  }
  2571  
  2572  // NewAsPathPrependAction creates AsPathPrependAction object.
  2573  // If ASN cannot be parsed, nil will be returned.
  2574  func NewAsPathPrependAction(action config.SetAsPathPrepend) (*AsPathPrependAction, error) {
  2575  	a := &AsPathPrependAction{
  2576  		repeat: action.RepeatN,
  2577  	}
  2578  	switch action.As {
  2579  	case "":
  2580  		if a.repeat == 0 {
  2581  			return nil, nil
  2582  		}
  2583  		return nil, fmt.Errorf("specify as to prepend")
  2584  	case "last-as":
  2585  		a.useLeftMost = true
  2586  	default:
  2587  		asn, err := strconv.ParseUint(action.As, 10, 32)
  2588  		if err != nil {
  2589  			return nil, fmt.Errorf("As number string invalid")
  2590  		}
  2591  		a.asn = uint32(asn)
  2592  	}
  2593  	return a, nil
  2594  }
  2595  
  2596  type NexthopAction struct {
  2597  	value net.IP
  2598  	self  bool
  2599  }
  2600  
  2601  func (a *NexthopAction) Type() ActionType {
  2602  	return ACTION_NEXTHOP
  2603  }
  2604  
  2605  func (a *NexthopAction) Apply(path *Path, options *PolicyOptions) *Path {
  2606  	if a.self {
  2607  		if options != nil && options.Info != nil && options.Info.LocalAddress != nil {
  2608  			path.SetNexthop(options.Info.LocalAddress)
  2609  		}
  2610  		return path
  2611  	}
  2612  	path.SetNexthop(a.value)
  2613  	return path
  2614  }
  2615  
  2616  func (a *NexthopAction) ToConfig() config.BgpNextHopType {
  2617  	if a.self {
  2618  		return config.BgpNextHopType("self")
  2619  	}
  2620  	return config.BgpNextHopType(a.value.String())
  2621  }
  2622  
  2623  func (a *NexthopAction) String() string {
  2624  	return string(a.ToConfig())
  2625  }
  2626  
  2627  func (a *NexthopAction) MarshalJSON() ([]byte, error) {
  2628  	return json.Marshal(a.ToConfig())
  2629  }
  2630  
  2631  func NewNexthopAction(c config.BgpNextHopType) (*NexthopAction, error) {
  2632  	switch strings.ToLower(string(c)) {
  2633  	case "":
  2634  		return nil, nil
  2635  	case "self":
  2636  		return &NexthopAction{
  2637  			self: true,
  2638  		}, nil
  2639  	}
  2640  	addr := net.ParseIP(string(c))
  2641  	if addr == nil {
  2642  		return nil, fmt.Errorf("invalid ip address format: %s", string(c))
  2643  	}
  2644  	return &NexthopAction{
  2645  		value: addr,
  2646  	}, nil
  2647  }
  2648  
  2649  type Statement struct {
  2650  	Name        string
  2651  	Conditions  []Condition
  2652  	RouteAction Action
  2653  	ModActions  []Action
  2654  }
  2655  
  2656  // evaluate each condition in the statement according to MatchSetOptions
  2657  func (s *Statement) Evaluate(p *Path, options *PolicyOptions) bool {
  2658  	for _, c := range s.Conditions {
  2659  		if !c.Evaluate(p, options) {
  2660  			return false
  2661  		}
  2662  	}
  2663  	return true
  2664  }
  2665  
  2666  func (s *Statement) Apply(path *Path, options *PolicyOptions) (RouteType, *Path) {
  2667  	result := s.Evaluate(path, options)
  2668  	if result {
  2669  		if len(s.ModActions) != 0 {
  2670  			// apply all modification actions
  2671  			path = path.Clone(path.IsWithdraw)
  2672  			for _, action := range s.ModActions {
  2673  				path = action.Apply(path, options)
  2674  			}
  2675  		}
  2676  		//Routing action
  2677  		if s.RouteAction == nil || reflect.ValueOf(s.RouteAction).IsNil() {
  2678  			return ROUTE_TYPE_NONE, path
  2679  		}
  2680  		p := s.RouteAction.Apply(path, options)
  2681  		if p == nil {
  2682  			return ROUTE_TYPE_REJECT, path
  2683  		}
  2684  		return ROUTE_TYPE_ACCEPT, path
  2685  	}
  2686  	return ROUTE_TYPE_NONE, path
  2687  }
  2688  
  2689  func (s *Statement) ToConfig() *config.Statement {
  2690  	return &config.Statement{
  2691  		Name: s.Name,
  2692  		Conditions: func() config.Conditions {
  2693  			cond := config.Conditions{}
  2694  			for _, c := range s.Conditions {
  2695  				switch c.(type) {
  2696  				case *PrefixCondition:
  2697  					v := c.(*PrefixCondition)
  2698  					cond.MatchPrefixSet = config.MatchPrefixSet{PrefixSet: v.set.Name(), MatchSetOptions: v.option.ConvertToMatchSetOptionsRestrictedType()}
  2699  				case *NeighborCondition:
  2700  					v := c.(*NeighborCondition)
  2701  					cond.MatchNeighborSet = config.MatchNeighborSet{NeighborSet: v.set.Name(), MatchSetOptions: v.option.ConvertToMatchSetOptionsRestrictedType()}
  2702  				case *AsPathLengthCondition:
  2703  					v := c.(*AsPathLengthCondition)
  2704  					cond.BgpConditions.AsPathLength = config.AsPathLength{Operator: config.IntToAttributeComparisonMap[int(v.operator)], Value: v.length}
  2705  				case *AsPathCondition:
  2706  					v := c.(*AsPathCondition)
  2707  					cond.BgpConditions.MatchAsPathSet = config.MatchAsPathSet{AsPathSet: v.set.Name(), MatchSetOptions: config.IntToMatchSetOptionsTypeMap[int(v.option)]}
  2708  				case *CommunityCondition:
  2709  					v := c.(*CommunityCondition)
  2710  					cond.BgpConditions.MatchCommunitySet = config.MatchCommunitySet{CommunitySet: v.set.Name(), MatchSetOptions: config.IntToMatchSetOptionsTypeMap[int(v.option)]}
  2711  				case *ExtCommunityCondition:
  2712  					v := c.(*ExtCommunityCondition)
  2713  					cond.BgpConditions.MatchExtCommunitySet = config.MatchExtCommunitySet{ExtCommunitySet: v.set.Name(), MatchSetOptions: config.IntToMatchSetOptionsTypeMap[int(v.option)]}
  2714  				case *LargeCommunityCondition:
  2715  					v := c.(*LargeCommunityCondition)
  2716  					cond.BgpConditions.MatchLargeCommunitySet = config.MatchLargeCommunitySet{LargeCommunitySet: v.set.Name(), MatchSetOptions: config.IntToMatchSetOptionsTypeMap[int(v.option)]}
  2717  				case *NextHopCondition:
  2718  					v := c.(*NextHopCondition)
  2719  					cond.BgpConditions.NextHopInList = v.set.List()
  2720  				case *RpkiValidationCondition:
  2721  					v := c.(*RpkiValidationCondition)
  2722  					cond.BgpConditions.RpkiValidationResult = v.result
  2723  				case *RouteTypeCondition:
  2724  					v := c.(*RouteTypeCondition)
  2725  					cond.BgpConditions.RouteType = v.typ
  2726  				case *AfiSafiInCondition:
  2727  					v := c.(*AfiSafiInCondition)
  2728  					res := make([]config.AfiSafiType, 0, len(v.routeFamilies))
  2729  					for _, rf := range v.routeFamilies {
  2730  						res = append(res, config.AfiSafiType(rf.String()))
  2731  					}
  2732  					cond.BgpConditions.AfiSafiInList = res
  2733  				}
  2734  			}
  2735  			return cond
  2736  		}(),
  2737  		Actions: func() config.Actions {
  2738  			act := config.Actions{}
  2739  			if s.RouteAction != nil && !reflect.ValueOf(s.RouteAction).IsNil() {
  2740  				a := s.RouteAction.(*RoutingAction)
  2741  				if a.AcceptRoute {
  2742  					act.RouteDisposition = config.ROUTE_DISPOSITION_ACCEPT_ROUTE
  2743  				} else {
  2744  					act.RouteDisposition = config.ROUTE_DISPOSITION_REJECT_ROUTE
  2745  				}
  2746  			} else {
  2747  				act.RouteDisposition = config.ROUTE_DISPOSITION_NONE
  2748  			}
  2749  			for _, a := range s.ModActions {
  2750  				switch a.(type) {
  2751  				case *AsPathPrependAction:
  2752  					act.BgpActions.SetAsPathPrepend = *a.(*AsPathPrependAction).ToConfig()
  2753  				case *CommunityAction:
  2754  					act.BgpActions.SetCommunity = *a.(*CommunityAction).ToConfig()
  2755  				case *ExtCommunityAction:
  2756  					act.BgpActions.SetExtCommunity = *a.(*ExtCommunityAction).ToConfig()
  2757  				case *LargeCommunityAction:
  2758  					act.BgpActions.SetLargeCommunity = *a.(*LargeCommunityAction).ToConfig()
  2759  				case *MedAction:
  2760  					act.BgpActions.SetMed = a.(*MedAction).ToConfig()
  2761  				case *LocalPrefAction:
  2762  					act.BgpActions.SetLocalPref = a.(*LocalPrefAction).ToConfig()
  2763  				case *NexthopAction:
  2764  					act.BgpActions.SetNextHop = a.(*NexthopAction).ToConfig()
  2765  				}
  2766  			}
  2767  			return act
  2768  		}(),
  2769  	}
  2770  }
  2771  
  2772  func (s *Statement) MarshalJSON() ([]byte, error) {
  2773  	return json.Marshal(s.ToConfig())
  2774  }
  2775  
  2776  type opType int
  2777  
  2778  const (
  2779  	ADD opType = iota
  2780  	REMOVE
  2781  	REPLACE
  2782  )
  2783  
  2784  func (lhs *Statement) mod(op opType, rhs *Statement) error {
  2785  	cs := make([]Condition, len(lhs.Conditions))
  2786  	copy(cs, lhs.Conditions)
  2787  	ra := lhs.RouteAction
  2788  	as := make([]Action, len(lhs.ModActions))
  2789  	copy(as, lhs.ModActions)
  2790  	for _, x := range rhs.Conditions {
  2791  		var c Condition
  2792  		i := 0
  2793  		for idx, y := range lhs.Conditions {
  2794  			if x.Type() == y.Type() {
  2795  				c = y
  2796  				i = idx
  2797  				break
  2798  			}
  2799  		}
  2800  		switch op {
  2801  		case ADD:
  2802  			if c != nil {
  2803  				return fmt.Errorf("condition %d is already set", x.Type())
  2804  			}
  2805  			if cs == nil {
  2806  				cs = make([]Condition, 0, len(rhs.Conditions))
  2807  			}
  2808  			cs = append(cs, x)
  2809  		case REMOVE:
  2810  			if c == nil {
  2811  				return fmt.Errorf("condition %d is not set", x.Type())
  2812  			}
  2813  			cs = append(cs[:i], cs[i+1:]...)
  2814  			if len(cs) == 0 {
  2815  				cs = nil
  2816  			}
  2817  		case REPLACE:
  2818  			if c == nil {
  2819  				return fmt.Errorf("condition %d is not set", x.Type())
  2820  			}
  2821  			cs[i] = x
  2822  		}
  2823  	}
  2824  	if rhs.RouteAction != nil && !reflect.ValueOf(rhs.RouteAction).IsNil() {
  2825  		switch op {
  2826  		case ADD:
  2827  			if lhs.RouteAction != nil && !reflect.ValueOf(lhs.RouteAction).IsNil() {
  2828  				return fmt.Errorf("route action is already set")
  2829  			}
  2830  			ra = rhs.RouteAction
  2831  		case REMOVE:
  2832  			if lhs.RouteAction == nil || reflect.ValueOf(lhs.RouteAction).IsNil() {
  2833  				return fmt.Errorf("route action is not set")
  2834  			}
  2835  			ra = nil
  2836  		case REPLACE:
  2837  			if lhs.RouteAction == nil || reflect.ValueOf(lhs.RouteAction).IsNil() {
  2838  				return fmt.Errorf("route action is not set")
  2839  			}
  2840  			ra = rhs.RouteAction
  2841  		}
  2842  	}
  2843  	for _, x := range rhs.ModActions {
  2844  		var a Action
  2845  		i := 0
  2846  		for idx, y := range lhs.ModActions {
  2847  			if x.Type() == y.Type() {
  2848  				a = y
  2849  				i = idx
  2850  				break
  2851  			}
  2852  		}
  2853  		switch op {
  2854  		case ADD:
  2855  			if a != nil {
  2856  				return fmt.Errorf("action %d is already set", x.Type())
  2857  			}
  2858  			if as == nil {
  2859  				as = make([]Action, 0, len(rhs.ModActions))
  2860  			}
  2861  			as = append(as, x)
  2862  		case REMOVE:
  2863  			if a == nil {
  2864  				return fmt.Errorf("action %d is not set", x.Type())
  2865  			}
  2866  			as = append(as[:i], as[i+1:]...)
  2867  			if len(as) == 0 {
  2868  				as = nil
  2869  			}
  2870  		case REPLACE:
  2871  			if a == nil {
  2872  				return fmt.Errorf("action %d is not set", x.Type())
  2873  			}
  2874  			as[i] = x
  2875  		}
  2876  	}
  2877  	lhs.Conditions = cs
  2878  	lhs.RouteAction = ra
  2879  	lhs.ModActions = as
  2880  	return nil
  2881  }
  2882  
  2883  func (lhs *Statement) Add(rhs *Statement) error {
  2884  	return lhs.mod(ADD, rhs)
  2885  }
  2886  
  2887  func (lhs *Statement) Remove(rhs *Statement) error {
  2888  	return lhs.mod(REMOVE, rhs)
  2889  }
  2890  
  2891  func (lhs *Statement) Replace(rhs *Statement) error {
  2892  	return lhs.mod(REPLACE, rhs)
  2893  }
  2894  
  2895  func NewStatement(c config.Statement) (*Statement, error) {
  2896  	if c.Name == "" {
  2897  		return nil, fmt.Errorf("empty statement name")
  2898  	}
  2899  	var ra Action
  2900  	var as []Action
  2901  	var cs []Condition
  2902  	var err error
  2903  	cfs := []func() (Condition, error){
  2904  		func() (Condition, error) {
  2905  			return NewPrefixCondition(c.Conditions.MatchPrefixSet)
  2906  		},
  2907  		func() (Condition, error) {
  2908  			return NewNeighborCondition(c.Conditions.MatchNeighborSet)
  2909  		},
  2910  		func() (Condition, error) {
  2911  			return NewAsPathLengthCondition(c.Conditions.BgpConditions.AsPathLength)
  2912  		},
  2913  		func() (Condition, error) {
  2914  			return NewRpkiValidationCondition(c.Conditions.BgpConditions.RpkiValidationResult)
  2915  		},
  2916  		func() (Condition, error) {
  2917  			return NewRouteTypeCondition(c.Conditions.BgpConditions.RouteType)
  2918  		},
  2919  		func() (Condition, error) {
  2920  			return NewAsPathCondition(c.Conditions.BgpConditions.MatchAsPathSet)
  2921  		},
  2922  		func() (Condition, error) {
  2923  			return NewCommunityCondition(c.Conditions.BgpConditions.MatchCommunitySet)
  2924  		},
  2925  		func() (Condition, error) {
  2926  			return NewExtCommunityCondition(c.Conditions.BgpConditions.MatchExtCommunitySet)
  2927  		},
  2928  		func() (Condition, error) {
  2929  			return NewLargeCommunityCondition(c.Conditions.BgpConditions.MatchLargeCommunitySet)
  2930  		},
  2931  		func() (Condition, error) {
  2932  			return NewNextHopCondition(c.Conditions.BgpConditions.NextHopInList)
  2933  		},
  2934  		func() (Condition, error) {
  2935  			return NewAfiSafiInCondition(c.Conditions.BgpConditions.AfiSafiInList)
  2936  		},
  2937  	}
  2938  	cs = make([]Condition, 0, len(cfs))
  2939  	for _, f := range cfs {
  2940  		c, err := f()
  2941  		if err != nil {
  2942  			return nil, err
  2943  		}
  2944  		if !reflect.ValueOf(c).IsNil() {
  2945  			cs = append(cs, c)
  2946  		}
  2947  	}
  2948  	ra, err = NewRoutingAction(c.Actions.RouteDisposition)
  2949  	if err != nil {
  2950  		return nil, err
  2951  	}
  2952  	afs := []func() (Action, error){
  2953  		func() (Action, error) {
  2954  			return NewCommunityAction(c.Actions.BgpActions.SetCommunity)
  2955  		},
  2956  		func() (Action, error) {
  2957  			return NewExtCommunityAction(c.Actions.BgpActions.SetExtCommunity)
  2958  		},
  2959  		func() (Action, error) {
  2960  			return NewLargeCommunityAction(c.Actions.BgpActions.SetLargeCommunity)
  2961  		},
  2962  		func() (Action, error) {
  2963  			return NewMedAction(c.Actions.BgpActions.SetMed)
  2964  		},
  2965  		func() (Action, error) {
  2966  			return NewLocalPrefAction(c.Actions.BgpActions.SetLocalPref)
  2967  		},
  2968  		func() (Action, error) {
  2969  			return NewAsPathPrependAction(c.Actions.BgpActions.SetAsPathPrepend)
  2970  		},
  2971  		func() (Action, error) {
  2972  			return NewNexthopAction(c.Actions.BgpActions.SetNextHop)
  2973  		},
  2974  	}
  2975  	as = make([]Action, 0, len(afs))
  2976  	for _, f := range afs {
  2977  		a, err := f()
  2978  		if err != nil {
  2979  			return nil, err
  2980  		}
  2981  		if !reflect.ValueOf(a).IsNil() {
  2982  			as = append(as, a)
  2983  		}
  2984  	}
  2985  	return &Statement{
  2986  		Name:        c.Name,
  2987  		Conditions:  cs,
  2988  		RouteAction: ra,
  2989  		ModActions:  as,
  2990  	}, nil
  2991  }
  2992  
  2993  type Policy struct {
  2994  	Name       string
  2995  	Statements []*Statement
  2996  }
  2997  
  2998  // Compare path with a policy's condition in stored order in the policy.
  2999  // If a condition match, then this function stops evaluation and
  3000  // subsequent conditions are skipped.
  3001  func (p *Policy) Apply(path *Path, options *PolicyOptions) (RouteType, *Path) {
  3002  	for _, stmt := range p.Statements {
  3003  		var result RouteType
  3004  		result, path = stmt.Apply(path, options)
  3005  		if result != ROUTE_TYPE_NONE {
  3006  			return result, path
  3007  		}
  3008  	}
  3009  	return ROUTE_TYPE_NONE, path
  3010  }
  3011  
  3012  func (p *Policy) ToConfig() *config.PolicyDefinition {
  3013  	ss := make([]config.Statement, 0, len(p.Statements))
  3014  	for _, s := range p.Statements {
  3015  		ss = append(ss, *s.ToConfig())
  3016  	}
  3017  	return &config.PolicyDefinition{
  3018  		Name:       p.Name,
  3019  		Statements: ss,
  3020  	}
  3021  }
  3022  
  3023  func (p *Policy) FillUp(m map[string]*Statement) error {
  3024  	stmts := make([]*Statement, 0, len(p.Statements))
  3025  	for _, x := range p.Statements {
  3026  		y, ok := m[x.Name]
  3027  		if !ok {
  3028  			return fmt.Errorf("not found statement %s", x.Name)
  3029  		}
  3030  		stmts = append(stmts, y)
  3031  	}
  3032  	p.Statements = stmts
  3033  	return nil
  3034  }
  3035  
  3036  func (lhs *Policy) Add(rhs *Policy) error {
  3037  	lhs.Statements = append(lhs.Statements, rhs.Statements...)
  3038  	return nil
  3039  }
  3040  
  3041  func (lhs *Policy) Remove(rhs *Policy) error {
  3042  	stmts := make([]*Statement, 0, len(lhs.Statements))
  3043  	for _, x := range lhs.Statements {
  3044  		found := false
  3045  		for _, y := range rhs.Statements {
  3046  			if x.Name == y.Name {
  3047  				found = true
  3048  				break
  3049  			}
  3050  		}
  3051  		if !found {
  3052  			stmts = append(stmts, x)
  3053  		}
  3054  	}
  3055  	lhs.Statements = stmts
  3056  	return nil
  3057  }
  3058  
  3059  func (lhs *Policy) Replace(rhs *Policy) error {
  3060  	lhs.Statements = rhs.Statements
  3061  	return nil
  3062  }
  3063  
  3064  func (p *Policy) MarshalJSON() ([]byte, error) {
  3065  	return json.Marshal(p.ToConfig())
  3066  }
  3067  
  3068  func NewPolicy(c config.PolicyDefinition) (*Policy, error) {
  3069  	if c.Name == "" {
  3070  		return nil, fmt.Errorf("empty policy name")
  3071  	}
  3072  	var st []*Statement
  3073  	stmts := c.Statements
  3074  	if len(stmts) != 0 {
  3075  		st = make([]*Statement, 0, len(stmts))
  3076  		for idx, stmt := range stmts {
  3077  			if stmt.Name == "" {
  3078  				stmt.Name = fmt.Sprintf("%s_stmt%d", c.Name, idx)
  3079  			}
  3080  			s, err := NewStatement(stmt)
  3081  			if err != nil {
  3082  				return nil, err
  3083  			}
  3084  			st = append(st, s)
  3085  		}
  3086  	}
  3087  	return &Policy{
  3088  		Name:       c.Name,
  3089  		Statements: st,
  3090  	}, nil
  3091  }
  3092  
  3093  type Policies []*Policy
  3094  
  3095  func (p Policies) Len() int {
  3096  	return len(p)
  3097  }
  3098  
  3099  func (p Policies) Swap(i, j int) {
  3100  	p[i], p[j] = p[j], p[i]
  3101  }
  3102  
  3103  func (p Policies) Less(i, j int) bool {
  3104  	return p[i].Name < p[j].Name
  3105  }
  3106  
  3107  type Assignment struct {
  3108  	importPolicies      []*Policy
  3109  	defaultImportPolicy RouteType
  3110  	exportPolicies      []*Policy
  3111  	defaultExportPolicy RouteType
  3112  }
  3113  
  3114  type RoutingPolicy struct {
  3115  	definedSetMap DefinedSetMap
  3116  	policyMap     map[string]*Policy
  3117  	statementMap  map[string]*Statement
  3118  	assignmentMap map[string]*Assignment
  3119  	mu            sync.RWMutex
  3120  }
  3121  
  3122  func (r *RoutingPolicy) ApplyPolicy(id string, dir PolicyDirection, before *Path, options *PolicyOptions) *Path {
  3123  	r.mu.RLock()
  3124  	defer r.mu.RUnlock()
  3125  
  3126  	if before == nil {
  3127  		return nil
  3128  	}
  3129  
  3130  	if before.IsWithdraw {
  3131  		return before
  3132  	}
  3133  	result := ROUTE_TYPE_NONE
  3134  	after := before
  3135  	for _, p := range r.getPolicy(id, dir) {
  3136  		result, after = p.Apply(after, options)
  3137  		if result != ROUTE_TYPE_NONE {
  3138  			break
  3139  		}
  3140  	}
  3141  	if result == ROUTE_TYPE_NONE {
  3142  		result = r.getDefaultPolicy(id, dir)
  3143  	}
  3144  	switch result {
  3145  	case ROUTE_TYPE_ACCEPT:
  3146  		return after
  3147  	default:
  3148  		return nil
  3149  	}
  3150  }
  3151  
  3152  func (r *RoutingPolicy) getPolicy(id string, dir PolicyDirection) []*Policy {
  3153  	a, ok := r.assignmentMap[id]
  3154  	if !ok {
  3155  		return nil
  3156  	}
  3157  	switch dir {
  3158  	case POLICY_DIRECTION_IMPORT:
  3159  		return a.importPolicies
  3160  	case POLICY_DIRECTION_EXPORT:
  3161  		return a.exportPolicies
  3162  	default:
  3163  		return nil
  3164  	}
  3165  }
  3166  
  3167  func (r *RoutingPolicy) getDefaultPolicy(id string, dir PolicyDirection) RouteType {
  3168  	a, ok := r.assignmentMap[id]
  3169  	if !ok {
  3170  		return ROUTE_TYPE_NONE
  3171  	}
  3172  	switch dir {
  3173  	case POLICY_DIRECTION_IMPORT:
  3174  		return a.defaultImportPolicy
  3175  	case POLICY_DIRECTION_EXPORT:
  3176  		return a.defaultExportPolicy
  3177  	default:
  3178  		return ROUTE_TYPE_NONE
  3179  	}
  3180  
  3181  }
  3182  
  3183  func (r *RoutingPolicy) setPolicy(id string, dir PolicyDirection, policies []*Policy) error {
  3184  	a, ok := r.assignmentMap[id]
  3185  	if !ok {
  3186  		a = &Assignment{}
  3187  	}
  3188  	switch dir {
  3189  	case POLICY_DIRECTION_IMPORT:
  3190  		a.importPolicies = policies
  3191  	case POLICY_DIRECTION_EXPORT:
  3192  		a.exportPolicies = policies
  3193  	}
  3194  	r.assignmentMap[id] = a
  3195  	return nil
  3196  }
  3197  
  3198  func (r *RoutingPolicy) setDefaultPolicy(id string, dir PolicyDirection, typ RouteType) error {
  3199  	a, ok := r.assignmentMap[id]
  3200  	if !ok {
  3201  		a = &Assignment{}
  3202  	}
  3203  	switch dir {
  3204  	case POLICY_DIRECTION_IMPORT:
  3205  		a.defaultImportPolicy = typ
  3206  	case POLICY_DIRECTION_EXPORT:
  3207  		a.defaultExportPolicy = typ
  3208  	}
  3209  	r.assignmentMap[id] = a
  3210  	return nil
  3211  }
  3212  
  3213  func (r *RoutingPolicy) getAssignmentFromConfig(dir PolicyDirection, a config.ApplyPolicy) ([]*Policy, RouteType, error) {
  3214  	var names []string
  3215  	var cdef config.DefaultPolicyType
  3216  	def := ROUTE_TYPE_ACCEPT
  3217  	c := a.Config
  3218  	switch dir {
  3219  	case POLICY_DIRECTION_IMPORT:
  3220  		names = c.ImportPolicyList
  3221  		cdef = c.DefaultImportPolicy
  3222  	case POLICY_DIRECTION_EXPORT:
  3223  		names = c.ExportPolicyList
  3224  		cdef = c.DefaultExportPolicy
  3225  	default:
  3226  		return nil, def, fmt.Errorf("invalid policy direction")
  3227  	}
  3228  	if cdef == config.DEFAULT_POLICY_TYPE_REJECT_ROUTE {
  3229  		def = ROUTE_TYPE_REJECT
  3230  	}
  3231  	ps := make([]*Policy, 0, len(names))
  3232  	seen := make(map[string]bool)
  3233  	for _, name := range names {
  3234  		p, ok := r.policyMap[name]
  3235  		if !ok {
  3236  			return nil, def, fmt.Errorf("not found policy %s", name)
  3237  		}
  3238  		if seen[name] {
  3239  			return nil, def, fmt.Errorf("duplicated policy %s", name)
  3240  		}
  3241  		seen[name] = true
  3242  		ps = append(ps, p)
  3243  	}
  3244  	return ps, def, nil
  3245  }
  3246  
  3247  func (r *RoutingPolicy) validateCondition(v Condition) (err error) {
  3248  	switch v.Type() {
  3249  	case CONDITION_PREFIX:
  3250  		m := r.definedSetMap[DEFINED_TYPE_PREFIX]
  3251  		if i, ok := m[v.Name()]; !ok {
  3252  			return fmt.Errorf("not found prefix set %s", v.Name())
  3253  		} else {
  3254  			c := v.(*PrefixCondition)
  3255  			c.set = i.(*PrefixSet)
  3256  		}
  3257  	case CONDITION_NEIGHBOR:
  3258  		m := r.definedSetMap[DEFINED_TYPE_NEIGHBOR]
  3259  		if i, ok := m[v.Name()]; !ok {
  3260  			return fmt.Errorf("not found neighbor set %s", v.Name())
  3261  		} else {
  3262  			c := v.(*NeighborCondition)
  3263  			c.set = i.(*NeighborSet)
  3264  		}
  3265  	case CONDITION_AS_PATH:
  3266  		m := r.definedSetMap[DEFINED_TYPE_AS_PATH]
  3267  		if i, ok := m[v.Name()]; !ok {
  3268  			return fmt.Errorf("not found as path set %s", v.Name())
  3269  		} else {
  3270  			c := v.(*AsPathCondition)
  3271  			c.set = i.(*AsPathSet)
  3272  		}
  3273  	case CONDITION_COMMUNITY:
  3274  		m := r.definedSetMap[DEFINED_TYPE_COMMUNITY]
  3275  		if i, ok := m[v.Name()]; !ok {
  3276  			return fmt.Errorf("not found community set %s", v.Name())
  3277  		} else {
  3278  			c := v.(*CommunityCondition)
  3279  			c.set = i.(*CommunitySet)
  3280  		}
  3281  	case CONDITION_EXT_COMMUNITY:
  3282  		m := r.definedSetMap[DEFINED_TYPE_EXT_COMMUNITY]
  3283  		if i, ok := m[v.Name()]; !ok {
  3284  			return fmt.Errorf("not found ext-community set %s", v.Name())
  3285  		} else {
  3286  			c := v.(*ExtCommunityCondition)
  3287  			c.set = i.(*ExtCommunitySet)
  3288  		}
  3289  	case CONDITION_LARGE_COMMUNITY:
  3290  		m := r.definedSetMap[DEFINED_TYPE_LARGE_COMMUNITY]
  3291  		if i, ok := m[v.Name()]; !ok {
  3292  			return fmt.Errorf("not found large-community set %s", v.Name())
  3293  		} else {
  3294  			c := v.(*LargeCommunityCondition)
  3295  			c.set = i.(*LargeCommunitySet)
  3296  		}
  3297  	case CONDITION_NEXT_HOP:
  3298  	case CONDITION_AFI_SAFI_IN:
  3299  	case CONDITION_AS_PATH_LENGTH:
  3300  	case CONDITION_RPKI:
  3301  	}
  3302  	return nil
  3303  }
  3304  
  3305  func (r *RoutingPolicy) inUse(d DefinedSet) bool {
  3306  	name := d.Name()
  3307  	for _, p := range r.policyMap {
  3308  		for _, s := range p.Statements {
  3309  			for _, c := range s.Conditions {
  3310  				if c.Set() != nil && c.Set().Name() == name {
  3311  					return true
  3312  				}
  3313  			}
  3314  		}
  3315  	}
  3316  	return false
  3317  }
  3318  
  3319  func (r *RoutingPolicy) statementInUse(x *Statement) bool {
  3320  	for _, p := range r.policyMap {
  3321  		for _, y := range p.Statements {
  3322  			if x.Name == y.Name {
  3323  				return true
  3324  			}
  3325  		}
  3326  	}
  3327  	return false
  3328  }
  3329  
  3330  func (r *RoutingPolicy) reload(c config.RoutingPolicy) error {
  3331  	dmap := make(map[DefinedType]map[string]DefinedSet)
  3332  	dmap[DEFINED_TYPE_PREFIX] = make(map[string]DefinedSet)
  3333  	d := c.DefinedSets
  3334  	for _, x := range d.PrefixSets {
  3335  		y, err := NewPrefixSet(x)
  3336  		if err != nil {
  3337  			return err
  3338  		}
  3339  		if y == nil {
  3340  			return fmt.Errorf("empty prefix set")
  3341  		}
  3342  		dmap[DEFINED_TYPE_PREFIX][y.Name()] = y
  3343  	}
  3344  	dmap[DEFINED_TYPE_NEIGHBOR] = make(map[string]DefinedSet)
  3345  	for _, x := range d.NeighborSets {
  3346  		y, err := NewNeighborSet(x)
  3347  		if err != nil {
  3348  			return err
  3349  		}
  3350  		if y == nil {
  3351  			return fmt.Errorf("empty neighbor set")
  3352  		}
  3353  		dmap[DEFINED_TYPE_NEIGHBOR][y.Name()] = y
  3354  	}
  3355  	//	dmap[DEFINED_TYPE_TAG] = make(map[string]DefinedSet)
  3356  	//	for _, x := range c.DefinedSets.TagSets{
  3357  	//		y, err := NewTagSet(x)
  3358  	//		if err != nil {
  3359  	//			return nil, err
  3360  	//		}
  3361  	//		dmap[DEFINED_TYPE_TAG][y.Name()] = y
  3362  	//	}
  3363  	bd := c.DefinedSets.BgpDefinedSets
  3364  	dmap[DEFINED_TYPE_AS_PATH] = make(map[string]DefinedSet)
  3365  	for _, x := range bd.AsPathSets {
  3366  		y, err := NewAsPathSet(x)
  3367  		if err != nil {
  3368  			return err
  3369  		}
  3370  		if y == nil {
  3371  			return fmt.Errorf("empty as path set")
  3372  		}
  3373  		dmap[DEFINED_TYPE_AS_PATH][y.Name()] = y
  3374  	}
  3375  	dmap[DEFINED_TYPE_COMMUNITY] = make(map[string]DefinedSet)
  3376  	for _, x := range bd.CommunitySets {
  3377  		y, err := NewCommunitySet(x)
  3378  		if err != nil {
  3379  			return err
  3380  		}
  3381  		if y == nil {
  3382  			return fmt.Errorf("empty community set")
  3383  		}
  3384  		dmap[DEFINED_TYPE_COMMUNITY][y.Name()] = y
  3385  	}
  3386  	dmap[DEFINED_TYPE_EXT_COMMUNITY] = make(map[string]DefinedSet)
  3387  	for _, x := range bd.ExtCommunitySets {
  3388  		y, err := NewExtCommunitySet(x)
  3389  		if err != nil {
  3390  			return err
  3391  		}
  3392  		if y == nil {
  3393  			return fmt.Errorf("empty ext-community set")
  3394  		}
  3395  		dmap[DEFINED_TYPE_EXT_COMMUNITY][y.Name()] = y
  3396  	}
  3397  	dmap[DEFINED_TYPE_LARGE_COMMUNITY] = make(map[string]DefinedSet)
  3398  	for _, x := range bd.LargeCommunitySets {
  3399  		y, err := NewLargeCommunitySet(x)
  3400  		if err != nil {
  3401  			return err
  3402  		}
  3403  		if y == nil {
  3404  			return fmt.Errorf("empty large-community set")
  3405  		}
  3406  		dmap[DEFINED_TYPE_LARGE_COMMUNITY][y.Name()] = y
  3407  	}
  3408  
  3409  	pmap := make(map[string]*Policy)
  3410  	smap := make(map[string]*Statement)
  3411  	for _, x := range c.PolicyDefinitions {
  3412  		y, err := NewPolicy(x)
  3413  		if err != nil {
  3414  			return err
  3415  		}
  3416  		if _, ok := pmap[y.Name]; ok {
  3417  			return fmt.Errorf("duplicated policy name. policy name must be unique.")
  3418  		}
  3419  		pmap[y.Name] = y
  3420  		for _, s := range y.Statements {
  3421  			_, ok := smap[s.Name]
  3422  			if ok {
  3423  				return fmt.Errorf("duplicated statement name. statement name must be unique.")
  3424  			}
  3425  			smap[s.Name] = s
  3426  		}
  3427  	}
  3428  
  3429  	// hacky
  3430  	oldMap := r.definedSetMap
  3431  	r.definedSetMap = dmap
  3432  	for _, y := range pmap {
  3433  		for _, s := range y.Statements {
  3434  			for _, c := range s.Conditions {
  3435  				if err := r.validateCondition(c); err != nil {
  3436  					r.definedSetMap = oldMap
  3437  					return err
  3438  				}
  3439  			}
  3440  		}
  3441  	}
  3442  
  3443  	r.definedSetMap = dmap
  3444  	r.policyMap = pmap
  3445  	r.statementMap = smap
  3446  	r.assignmentMap = make(map[string]*Assignment)
  3447  	// allow all routes coming in and going out by default
  3448  	r.setDefaultPolicy(GLOBAL_RIB_NAME, POLICY_DIRECTION_IMPORT, ROUTE_TYPE_ACCEPT)
  3449  	r.setDefaultPolicy(GLOBAL_RIB_NAME, POLICY_DIRECTION_EXPORT, ROUTE_TYPE_ACCEPT)
  3450  	return nil
  3451  }
  3452  
  3453  func (r *RoutingPolicy) GetDefinedSet(typ DefinedType, name string) (*config.DefinedSets, error) {
  3454  	r.mu.RLock()
  3455  
  3456  	set, ok := r.definedSetMap[typ]
  3457  	if !ok {
  3458  		return nil, fmt.Errorf("invalid defined-set type: %d", typ)
  3459  	}
  3460  
  3461  	var dl DefinedSetList
  3462  	for _, s := range set {
  3463  		dl = append(dl, s)
  3464  	}
  3465  	r.mu.RUnlock()
  3466  
  3467  	sort.Sort(dl)
  3468  
  3469  	sets := &config.DefinedSets{
  3470  		PrefixSets:   make([]config.PrefixSet, 0),
  3471  		NeighborSets: make([]config.NeighborSet, 0),
  3472  		BgpDefinedSets: config.BgpDefinedSets{
  3473  			CommunitySets:      make([]config.CommunitySet, 0),
  3474  			ExtCommunitySets:   make([]config.ExtCommunitySet, 0),
  3475  			LargeCommunitySets: make([]config.LargeCommunitySet, 0),
  3476  			AsPathSets:         make([]config.AsPathSet, 0),
  3477  		},
  3478  	}
  3479  	for _, s := range dl {
  3480  		if name != "" && s.Name() != name {
  3481  			continue
  3482  		}
  3483  		switch s.(type) {
  3484  		case *PrefixSet:
  3485  			sets.PrefixSets = append(sets.PrefixSets, *s.(*PrefixSet).ToConfig())
  3486  		case *NeighborSet:
  3487  			sets.NeighborSets = append(sets.NeighborSets, *s.(*NeighborSet).ToConfig())
  3488  		case *CommunitySet:
  3489  			sets.BgpDefinedSets.CommunitySets = append(sets.BgpDefinedSets.CommunitySets, *s.(*CommunitySet).ToConfig())
  3490  		case *ExtCommunitySet:
  3491  			sets.BgpDefinedSets.ExtCommunitySets = append(sets.BgpDefinedSets.ExtCommunitySets, *s.(*ExtCommunitySet).ToConfig())
  3492  		case *LargeCommunitySet:
  3493  			sets.BgpDefinedSets.LargeCommunitySets = append(sets.BgpDefinedSets.LargeCommunitySets, *s.(*LargeCommunitySet).ToConfig())
  3494  		case *AsPathSet:
  3495  			sets.BgpDefinedSets.AsPathSets = append(sets.BgpDefinedSets.AsPathSets, *s.(*AsPathSet).ToConfig())
  3496  		}
  3497  	}
  3498  	return sets, nil
  3499  }
  3500  
  3501  func (r *RoutingPolicy) AddDefinedSet(s DefinedSet) error {
  3502  	r.mu.Lock()
  3503  	defer r.mu.Unlock()
  3504  
  3505  	if m, ok := r.definedSetMap[s.Type()]; !ok {
  3506  		return fmt.Errorf("invalid defined-set type: %d", s.Type())
  3507  	} else {
  3508  		if d, ok := m[s.Name()]; ok {
  3509  			if err := d.Append(s); err != nil {
  3510  				return err
  3511  			}
  3512  		} else {
  3513  			m[s.Name()] = s
  3514  		}
  3515  	}
  3516  	return nil
  3517  }
  3518  
  3519  func (r *RoutingPolicy) DeleteDefinedSet(a DefinedSet, all bool) (err error) {
  3520  	r.mu.Lock()
  3521  	defer r.mu.Unlock()
  3522  
  3523  	if m, ok := r.definedSetMap[a.Type()]; !ok {
  3524  		err = fmt.Errorf("invalid defined-set type: %d", a.Type())
  3525  	} else {
  3526  		d, ok := m[a.Name()]
  3527  		if !ok {
  3528  			return fmt.Errorf("not found defined-set: %s", a.Name())
  3529  		}
  3530  		if all {
  3531  			if r.inUse(d) {
  3532  				err = fmt.Errorf("can't delete. defined-set %s is in use", a.Name())
  3533  			} else {
  3534  				delete(m, a.Name())
  3535  			}
  3536  		} else {
  3537  			err = d.Remove(a)
  3538  		}
  3539  	}
  3540  	return err
  3541  }
  3542  
  3543  func (r *RoutingPolicy) GetStatement(name string) []*config.Statement {
  3544  	r.mu.RLock()
  3545  	defer r.mu.RUnlock()
  3546  
  3547  	l := make([]*config.Statement, 0, len(r.statementMap))
  3548  	for _, st := range r.statementMap {
  3549  		if name != "" && name != st.Name {
  3550  			continue
  3551  		}
  3552  		l = append(l, st.ToConfig())
  3553  	}
  3554  	return l
  3555  }
  3556  
  3557  func (r *RoutingPolicy) AddStatement(st *Statement) (err error) {
  3558  	r.mu.Lock()
  3559  	defer r.mu.Unlock()
  3560  
  3561  	for _, c := range st.Conditions {
  3562  		if err = r.validateCondition(c); err != nil {
  3563  			return
  3564  		}
  3565  	}
  3566  	m := r.statementMap
  3567  	name := st.Name
  3568  	if d, ok := m[name]; ok {
  3569  		err = d.Add(st)
  3570  	} else {
  3571  		m[name] = st
  3572  	}
  3573  
  3574  	return err
  3575  }
  3576  
  3577  func (r *RoutingPolicy) DeleteStatement(st *Statement, all bool) (err error) {
  3578  	r.mu.Lock()
  3579  	defer r.mu.Unlock()
  3580  
  3581  	m := r.statementMap
  3582  	name := st.Name
  3583  	if d, ok := m[name]; ok {
  3584  		if all {
  3585  			if r.statementInUse(d) {
  3586  				err = fmt.Errorf("can't delete. statement %s is in use", name)
  3587  			} else {
  3588  				delete(m, name)
  3589  			}
  3590  		} else {
  3591  			err = d.Remove(st)
  3592  		}
  3593  	} else {
  3594  		err = fmt.Errorf("not found statement: %s", name)
  3595  	}
  3596  	return err
  3597  }
  3598  
  3599  func (r *RoutingPolicy) GetPolicy(name string) []*config.PolicyDefinition {
  3600  	r.mu.RLock()
  3601  
  3602  	var ps Policies
  3603  	for _, p := range r.policyMap {
  3604  		if name != "" && name != p.Name {
  3605  			continue
  3606  		}
  3607  		ps = append(ps, p)
  3608  	}
  3609  	r.mu.RUnlock()
  3610  
  3611  	sort.Sort(ps)
  3612  
  3613  	l := make([]*config.PolicyDefinition, 0, len(ps))
  3614  	for _, p := range ps {
  3615  		l = append(l, p.ToConfig())
  3616  	}
  3617  	return l
  3618  }
  3619  
  3620  func (r *RoutingPolicy) AddPolicy(x *Policy, refer bool) (err error) {
  3621  	r.mu.Lock()
  3622  	defer r.mu.Unlock()
  3623  
  3624  	for _, st := range x.Statements {
  3625  		for _, c := range st.Conditions {
  3626  			if err = r.validateCondition(c); err != nil {
  3627  				return
  3628  			}
  3629  		}
  3630  	}
  3631  
  3632  	pMap := r.policyMap
  3633  	sMap := r.statementMap
  3634  	name := x.Name
  3635  	y, ok := pMap[name]
  3636  	if refer {
  3637  		err = x.FillUp(sMap)
  3638  	} else {
  3639  		for _, st := range x.Statements {
  3640  			if _, ok := sMap[st.Name]; ok {
  3641  				err = fmt.Errorf("statement %s already defined", st.Name)
  3642  				return
  3643  			}
  3644  			sMap[st.Name] = st
  3645  		}
  3646  	}
  3647  	if ok {
  3648  		err = y.Add(x)
  3649  	} else {
  3650  		pMap[name] = x
  3651  	}
  3652  
  3653  	return err
  3654  }
  3655  
  3656  func (r *RoutingPolicy) DeletePolicy(x *Policy, all, preserve bool, activeId []string) (err error) {
  3657  	r.mu.Lock()
  3658  	defer r.mu.Unlock()
  3659  
  3660  	pMap := r.policyMap
  3661  	sMap := r.statementMap
  3662  	name := x.Name
  3663  	y, ok := pMap[name]
  3664  	if !ok {
  3665  		err = fmt.Errorf("not found policy: %s", name)
  3666  		return
  3667  	}
  3668  	inUse := func(ids []string) bool {
  3669  		for _, id := range ids {
  3670  			for _, dir := range []PolicyDirection{POLICY_DIRECTION_EXPORT, POLICY_DIRECTION_EXPORT} {
  3671  				for _, y := range r.getPolicy(id, dir) {
  3672  					if x.Name == y.Name {
  3673  						return true
  3674  					}
  3675  				}
  3676  			}
  3677  		}
  3678  		return false
  3679  	}
  3680  
  3681  	if all {
  3682  		if inUse(activeId) {
  3683  			err = fmt.Errorf("can't delete. policy %s is in use", name)
  3684  			return
  3685  		}
  3686  		log.WithFields(log.Fields{
  3687  			"Topic": "Policy",
  3688  			"Key":   name,
  3689  		}).Debug("delete policy")
  3690  		delete(pMap, name)
  3691  	} else {
  3692  		err = y.Remove(x)
  3693  	}
  3694  	if err == nil && !preserve {
  3695  		for _, st := range y.Statements {
  3696  			if !r.statementInUse(st) {
  3697  				log.WithFields(log.Fields{
  3698  					"Topic": "Policy",
  3699  					"Key":   st.Name,
  3700  				}).Debug("delete unused statement")
  3701  				delete(sMap, st.Name)
  3702  			}
  3703  		}
  3704  	}
  3705  	return err
  3706  }
  3707  
  3708  func (r *RoutingPolicy) GetPolicyAssignment(id string, dir PolicyDirection) (RouteType, []*Policy, error) {
  3709  	r.mu.RLock()
  3710  	defer r.mu.RUnlock()
  3711  
  3712  	rt := r.getDefaultPolicy(id, dir)
  3713  	l := make([]*Policy, 0)
  3714  	l = append(l, r.getPolicy(id, dir)...)
  3715  	return rt, l, nil
  3716  }
  3717  
  3718  func (r *RoutingPolicy) AddPolicyAssignment(id string, dir PolicyDirection, policies []*config.PolicyDefinition, def RouteType) (err error) {
  3719  	r.mu.Lock()
  3720  	defer r.mu.Unlock()
  3721  
  3722  	ps := make([]*Policy, 0, len(policies))
  3723  	seen := make(map[string]bool)
  3724  	for _, x := range policies {
  3725  		p, ok := r.policyMap[x.Name]
  3726  		if !ok {
  3727  			err = fmt.Errorf("not found policy %s", x.Name)
  3728  			return
  3729  		}
  3730  		if seen[x.Name] {
  3731  			err = fmt.Errorf("duplicated policy %s", x.Name)
  3732  			return
  3733  		}
  3734  		seen[x.Name] = true
  3735  		ps = append(ps, p)
  3736  	}
  3737  	cur := r.getPolicy(id, dir)
  3738  	if cur == nil {
  3739  		err = r.setPolicy(id, dir, ps)
  3740  	} else {
  3741  		seen = make(map[string]bool)
  3742  		ps = append(cur, ps...)
  3743  		for _, x := range ps {
  3744  			if seen[x.Name] {
  3745  				err = fmt.Errorf("duplicated policy %s", x.Name)
  3746  				return
  3747  			}
  3748  			seen[x.Name] = true
  3749  		}
  3750  		err = r.setPolicy(id, dir, ps)
  3751  	}
  3752  	if err == nil && def != ROUTE_TYPE_NONE {
  3753  		err = r.setDefaultPolicy(id, dir, def)
  3754  	}
  3755  	return err
  3756  }
  3757  
  3758  func (r *RoutingPolicy) DeletePolicyAssignment(id string, dir PolicyDirection, policies []*config.PolicyDefinition, all bool) (err error) {
  3759  	r.mu.Lock()
  3760  	defer r.mu.Unlock()
  3761  
  3762  	ps := make([]*Policy, 0, len(policies))
  3763  	seen := make(map[string]bool)
  3764  	for _, x := range policies {
  3765  		p, ok := r.policyMap[x.Name]
  3766  		if !ok {
  3767  			err = fmt.Errorf("not found policy %s", x.Name)
  3768  			return
  3769  		}
  3770  		if seen[x.Name] {
  3771  			err = fmt.Errorf("duplicated policy %s", x.Name)
  3772  			return
  3773  		}
  3774  		seen[x.Name] = true
  3775  		ps = append(ps, p)
  3776  	}
  3777  	cur := r.getPolicy(id, dir)
  3778  
  3779  	if all {
  3780  		err = r.setPolicy(id, dir, nil)
  3781  		if err != nil {
  3782  			return
  3783  		}
  3784  		err = r.setDefaultPolicy(id, dir, ROUTE_TYPE_NONE)
  3785  	} else {
  3786  		l := len(cur) - len(ps)
  3787  		if l < 0 {
  3788  			// try to remove more than the assigned policies...
  3789  			l = len(cur)
  3790  		}
  3791  		n := make([]*Policy, 0, l)
  3792  		for _, y := range cur {
  3793  			found := false
  3794  			for _, x := range ps {
  3795  				if x.Name == y.Name {
  3796  					found = true
  3797  					break
  3798  				}
  3799  			}
  3800  			if !found {
  3801  				n = append(n, y)
  3802  			}
  3803  		}
  3804  		err = r.setPolicy(id, dir, n)
  3805  	}
  3806  	return err
  3807  }
  3808  
  3809  func (r *RoutingPolicy) SetPolicyAssignment(id string, dir PolicyDirection, policies []*config.PolicyDefinition, def RouteType) (err error) {
  3810  	r.mu.Lock()
  3811  	defer r.mu.Unlock()
  3812  
  3813  	ps := make([]*Policy, 0, len(policies))
  3814  	seen := make(map[string]bool)
  3815  	for _, x := range policies {
  3816  		p, ok := r.policyMap[x.Name]
  3817  		if !ok {
  3818  			err = fmt.Errorf("not found policy %s", x.Name)
  3819  			return
  3820  		}
  3821  		if seen[x.Name] {
  3822  			err = fmt.Errorf("duplicated policy %s", x.Name)
  3823  			return
  3824  		}
  3825  		seen[x.Name] = true
  3826  		ps = append(ps, p)
  3827  	}
  3828  	r.getPolicy(id, dir)
  3829  	err = r.setPolicy(id, dir, ps)
  3830  	if err == nil && def != ROUTE_TYPE_NONE {
  3831  		err = r.setDefaultPolicy(id, dir, def)
  3832  	}
  3833  	return err
  3834  }
  3835  
  3836  func (r *RoutingPolicy) Reset(rp *config.RoutingPolicy, ap map[string]config.ApplyPolicy) error {
  3837  	r.mu.Lock()
  3838  	defer r.mu.Unlock()
  3839  
  3840  	if rp != nil {
  3841  		if err := r.reload(*rp); err != nil {
  3842  			log.WithFields(log.Fields{
  3843  				"Topic": "Policy",
  3844  			}).Errorf("failed to create routing policy: %s", err)
  3845  			return err
  3846  		}
  3847  	}
  3848  
  3849  	for id, c := range ap {
  3850  		for _, dir := range []PolicyDirection{POLICY_DIRECTION_IMPORT, POLICY_DIRECTION_EXPORT} {
  3851  			ps, def, err := r.getAssignmentFromConfig(dir, c)
  3852  			if err != nil {
  3853  				log.WithFields(log.Fields{
  3854  					"Topic": "Policy",
  3855  					"Dir":   dir,
  3856  				}).Errorf("failed to get policy info: %s", err)
  3857  				continue
  3858  			}
  3859  			r.setDefaultPolicy(id, dir, def)
  3860  			r.setPolicy(id, dir, ps)
  3861  		}
  3862  	}
  3863  	return nil
  3864  }
  3865  
  3866  func NewRoutingPolicy() *RoutingPolicy {
  3867  	return &RoutingPolicy{
  3868  		definedSetMap: make(map[DefinedType]map[string]DefinedSet),
  3869  		policyMap:     make(map[string]*Policy),
  3870  		statementMap:  make(map[string]*Statement),
  3871  		assignmentMap: make(map[string]*Assignment),
  3872  	}
  3873  }
  3874  
  3875  func CanImportToVrf(v *Vrf, path *Path) bool {
  3876  	f := func(arg []bgp.ExtendedCommunityInterface) []string {
  3877  		ret := make([]string, 0, len(arg))
  3878  		for _, a := range arg {
  3879  			ret = append(ret, fmt.Sprintf("RT:%s", a.String()))
  3880  		}
  3881  		return ret
  3882  	}
  3883  	set, _ := NewExtCommunitySet(config.ExtCommunitySet{
  3884  		ExtCommunitySetName: v.Name,
  3885  		ExtCommunityList:    f(v.ImportRt),
  3886  	})
  3887  	matchSet := config.MatchExtCommunitySet{
  3888  		ExtCommunitySet: v.Name,
  3889  		MatchSetOptions: config.MATCH_SET_OPTIONS_TYPE_ANY,
  3890  	}
  3891  	c, _ := NewExtCommunityCondition(matchSet)
  3892  	c.set = set
  3893  	return c.Evaluate(path, nil)
  3894  }
  3895  
  3896  type PolicyAssignment struct {
  3897  	Name     string
  3898  	Type     PolicyDirection
  3899  	Policies []*Policy
  3900  	Default  RouteType
  3901  }
  3902  
  3903  var _regexpMedActionType = regexp.MustCompile(`([+-]?)(\d+)`)
  3904  
  3905  func toStatementApi(s *config.Statement) *api.Statement {
  3906  	cs := &api.Conditions{}
  3907  	o, _ := NewMatchOption(s.Conditions.MatchPrefixSet.MatchSetOptions)
  3908  	if s.Conditions.MatchPrefixSet.PrefixSet != "" {
  3909  		cs.PrefixSet = &api.MatchSet{
  3910  			MatchType: api.MatchType(o),
  3911  			Name:      s.Conditions.MatchPrefixSet.PrefixSet,
  3912  		}
  3913  	}
  3914  	if s.Conditions.MatchNeighborSet.NeighborSet != "" {
  3915  		o, _ := NewMatchOption(s.Conditions.MatchNeighborSet.MatchSetOptions)
  3916  		cs.NeighborSet = &api.MatchSet{
  3917  			MatchType: api.MatchType(o),
  3918  			Name:      s.Conditions.MatchNeighborSet.NeighborSet,
  3919  		}
  3920  	}
  3921  	if s.Conditions.BgpConditions.AsPathLength.Operator != "" {
  3922  		cs.AsPathLength = &api.AsPathLength{
  3923  			Length:     s.Conditions.BgpConditions.AsPathLength.Value,
  3924  			LengthType: api.AsPathLengthType(s.Conditions.BgpConditions.AsPathLength.Operator.ToInt()),
  3925  		}
  3926  	}
  3927  	if s.Conditions.BgpConditions.MatchAsPathSet.AsPathSet != "" {
  3928  		cs.AsPathSet = &api.MatchSet{
  3929  			MatchType: api.MatchType(s.Conditions.BgpConditions.MatchAsPathSet.MatchSetOptions.ToInt()),
  3930  			Name:      s.Conditions.BgpConditions.MatchAsPathSet.AsPathSet,
  3931  		}
  3932  	}
  3933  	if s.Conditions.BgpConditions.MatchCommunitySet.CommunitySet != "" {
  3934  		cs.CommunitySet = &api.MatchSet{
  3935  			MatchType: api.MatchType(s.Conditions.BgpConditions.MatchCommunitySet.MatchSetOptions.ToInt()),
  3936  			Name:      s.Conditions.BgpConditions.MatchCommunitySet.CommunitySet,
  3937  		}
  3938  	}
  3939  	if s.Conditions.BgpConditions.MatchExtCommunitySet.ExtCommunitySet != "" {
  3940  		cs.ExtCommunitySet = &api.MatchSet{
  3941  			MatchType: api.MatchType(s.Conditions.BgpConditions.MatchExtCommunitySet.MatchSetOptions.ToInt()),
  3942  			Name:      s.Conditions.BgpConditions.MatchExtCommunitySet.ExtCommunitySet,
  3943  		}
  3944  	}
  3945  	if s.Conditions.BgpConditions.MatchLargeCommunitySet.LargeCommunitySet != "" {
  3946  		cs.LargeCommunitySet = &api.MatchSet{
  3947  			MatchType: api.MatchType(s.Conditions.BgpConditions.MatchLargeCommunitySet.MatchSetOptions.ToInt()),
  3948  			Name:      s.Conditions.BgpConditions.MatchLargeCommunitySet.LargeCommunitySet,
  3949  		}
  3950  	}
  3951  	if s.Conditions.BgpConditions.RouteType != "" {
  3952  		cs.RouteType = api.Conditions_RouteType(s.Conditions.BgpConditions.RouteType.ToInt())
  3953  	}
  3954  	if len(s.Conditions.BgpConditions.NextHopInList) > 0 {
  3955  		cs.NextHopInList = s.Conditions.BgpConditions.NextHopInList
  3956  	}
  3957  	if s.Conditions.BgpConditions.AfiSafiInList != nil {
  3958  		afiSafiIn := make([]*api.Family, 0)
  3959  		for _, afiSafiType := range s.Conditions.BgpConditions.AfiSafiInList {
  3960  			if mapped, ok := bgp.AddressFamilyValueMap[string(afiSafiType)]; ok {
  3961  				afi, safi := bgp.RouteFamilyToAfiSafi(mapped)
  3962  				afiSafiIn = append(afiSafiIn, &api.Family{Afi: api.Family_Afi(afi), Safi: api.Family_Safi(safi)})
  3963  			}
  3964  		}
  3965  		cs.AfiSafiIn = afiSafiIn
  3966  	}
  3967  	cs.RpkiResult = int32(s.Conditions.BgpConditions.RpkiValidationResult.ToInt())
  3968  	as := &api.Actions{
  3969  		RouteAction: func() api.RouteAction {
  3970  			switch s.Actions.RouteDisposition {
  3971  			case config.ROUTE_DISPOSITION_ACCEPT_ROUTE:
  3972  				return api.RouteAction_ACCEPT
  3973  			case config.ROUTE_DISPOSITION_REJECT_ROUTE:
  3974  				return api.RouteAction_REJECT
  3975  			}
  3976  			return api.RouteAction_NONE
  3977  		}(),
  3978  		Community: func() *api.CommunityAction {
  3979  			if len(s.Actions.BgpActions.SetCommunity.SetCommunityMethod.CommunitiesList) == 0 {
  3980  				return nil
  3981  			}
  3982  			return &api.CommunityAction{
  3983  				ActionType:  api.CommunityActionType(config.BgpSetCommunityOptionTypeToIntMap[config.BgpSetCommunityOptionType(s.Actions.BgpActions.SetCommunity.Options)]),
  3984  				Communities: s.Actions.BgpActions.SetCommunity.SetCommunityMethod.CommunitiesList}
  3985  		}(),
  3986  		Med: func() *api.MedAction {
  3987  			medStr := strings.TrimSpace(string(s.Actions.BgpActions.SetMed))
  3988  			if len(medStr) == 0 {
  3989  				return nil
  3990  			}
  3991  			matches := _regexpMedActionType.FindStringSubmatch(medStr)
  3992  			if len(matches) == 0 {
  3993  				return nil
  3994  			}
  3995  			action := api.MedActionType_MED_REPLACE
  3996  			switch matches[1] {
  3997  			case "+", "-":
  3998  				action = api.MedActionType_MED_MOD
  3999  			}
  4000  			value, err := strconv.ParseInt(matches[1]+matches[2], 10, 64)
  4001  			if err != nil {
  4002  				return nil
  4003  			}
  4004  			return &api.MedAction{
  4005  				Value:      value,
  4006  				ActionType: action,
  4007  			}
  4008  		}(),
  4009  		AsPrepend: func() *api.AsPrependAction {
  4010  			if len(s.Actions.BgpActions.SetAsPathPrepend.As) == 0 {
  4011  				return nil
  4012  			}
  4013  			var asn uint64
  4014  			useleft := false
  4015  			if s.Actions.BgpActions.SetAsPathPrepend.As != "last-as" {
  4016  				asn, _ = strconv.ParseUint(s.Actions.BgpActions.SetAsPathPrepend.As, 10, 32)
  4017  			} else {
  4018  				useleft = true
  4019  			}
  4020  			return &api.AsPrependAction{
  4021  				Asn:         uint32(asn),
  4022  				Repeat:      uint32(s.Actions.BgpActions.SetAsPathPrepend.RepeatN),
  4023  				UseLeftMost: useleft,
  4024  			}
  4025  		}(),
  4026  		ExtCommunity: func() *api.CommunityAction {
  4027  			if len(s.Actions.BgpActions.SetExtCommunity.SetExtCommunityMethod.CommunitiesList) == 0 {
  4028  				return nil
  4029  			}
  4030  			return &api.CommunityAction{
  4031  				ActionType:  api.CommunityActionType(config.BgpSetCommunityOptionTypeToIntMap[config.BgpSetCommunityOptionType(s.Actions.BgpActions.SetExtCommunity.Options)]),
  4032  				Communities: s.Actions.BgpActions.SetExtCommunity.SetExtCommunityMethod.CommunitiesList,
  4033  			}
  4034  		}(),
  4035  		LargeCommunity: func() *api.CommunityAction {
  4036  			if len(s.Actions.BgpActions.SetLargeCommunity.SetLargeCommunityMethod.CommunitiesList) == 0 {
  4037  				return nil
  4038  			}
  4039  			return &api.CommunityAction{
  4040  				ActionType:  api.CommunityActionType(config.BgpSetCommunityOptionTypeToIntMap[config.BgpSetCommunityOptionType(s.Actions.BgpActions.SetLargeCommunity.Options)]),
  4041  				Communities: s.Actions.BgpActions.SetLargeCommunity.SetLargeCommunityMethod.CommunitiesList,
  4042  			}
  4043  		}(),
  4044  		Nexthop: func() *api.NexthopAction {
  4045  			if len(string(s.Actions.BgpActions.SetNextHop)) == 0 {
  4046  				return nil
  4047  			}
  4048  
  4049  			if string(s.Actions.BgpActions.SetNextHop) == "self" {
  4050  				return &api.NexthopAction{
  4051  					Self: true,
  4052  				}
  4053  			}
  4054  			return &api.NexthopAction{
  4055  				Address: string(s.Actions.BgpActions.SetNextHop),
  4056  			}
  4057  		}(),
  4058  		LocalPref: func() *api.LocalPrefAction {
  4059  			if s.Actions.BgpActions.SetLocalPref == 0 {
  4060  				return nil
  4061  			}
  4062  			return &api.LocalPrefAction{Value: s.Actions.BgpActions.SetLocalPref}
  4063  		}(),
  4064  	}
  4065  	return &api.Statement{
  4066  		Name:       s.Name,
  4067  		Conditions: cs,
  4068  		Actions:    as,
  4069  	}
  4070  }
  4071  
  4072  func NewAPIPolicyFromTableStruct(p *Policy) *api.Policy {
  4073  	return ToPolicyApi(p.ToConfig())
  4074  }
  4075  
  4076  func ToPolicyApi(p *config.PolicyDefinition) *api.Policy {
  4077  	return &api.Policy{
  4078  		Name: p.Name,
  4079  		Statements: func() []*api.Statement {
  4080  			l := make([]*api.Statement, 0)
  4081  			for _, s := range p.Statements {
  4082  				l = append(l, toStatementApi(&s))
  4083  			}
  4084  			return l
  4085  		}(),
  4086  	}
  4087  }
  4088  
  4089  func NewAPIPolicyAssignmentFromTableStruct(t *PolicyAssignment) *api.PolicyAssignment {
  4090  	return &api.PolicyAssignment{
  4091  		Direction: func() api.PolicyDirection {
  4092  			switch t.Type {
  4093  			case POLICY_DIRECTION_IMPORT:
  4094  				return api.PolicyDirection_IMPORT
  4095  			case POLICY_DIRECTION_EXPORT:
  4096  				return api.PolicyDirection_EXPORT
  4097  			}
  4098  			log.Errorf("invalid policy-type: %s", t.Type)
  4099  			return api.PolicyDirection_UNKNOWN
  4100  		}(),
  4101  		DefaultAction: func() api.RouteAction {
  4102  			switch t.Default {
  4103  			case ROUTE_TYPE_ACCEPT:
  4104  				return api.RouteAction_ACCEPT
  4105  			case ROUTE_TYPE_REJECT:
  4106  				return api.RouteAction_REJECT
  4107  			}
  4108  			return api.RouteAction_NONE
  4109  		}(),
  4110  		Name: t.Name,
  4111  		Policies: func() []*api.Policy {
  4112  			l := make([]*api.Policy, 0)
  4113  			for _, p := range t.Policies {
  4114  				l = append(l, NewAPIPolicyFromTableStruct(p))
  4115  			}
  4116  			return l
  4117  		}(),
  4118  	}
  4119  }
  4120  
  4121  func NewAPIRoutingPolicyFromConfigStruct(c *config.RoutingPolicy) (*api.RoutingPolicy, error) {
  4122  	definedSets, err := config.NewAPIDefinedSetsFromConfigStruct(&c.DefinedSets)
  4123  	if err != nil {
  4124  		return nil, err
  4125  	}
  4126  	policies := make([]*api.Policy, 0, len(c.PolicyDefinitions))
  4127  	for _, policy := range c.PolicyDefinitions {
  4128  		policies = append(policies, ToPolicyApi(&policy))
  4129  	}
  4130  
  4131  	return &api.RoutingPolicy{
  4132  		DefinedSets: definedSets,
  4133  		Policies:    policies,
  4134  	}, nil
  4135  }