github.com/osrg/gobgp/v3@v3.30.0/internal/pkg/table/table_test.go (about)

     1  // Copyright (C) 2014 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  	"testing"
    20  	"time"
    21  
    22  	"github.com/osrg/gobgp/v3/pkg/packet/bgp"
    23  
    24  	"github.com/stretchr/testify/assert"
    25  )
    26  
    27  func TestLookupLonger(t *testing.T) {
    28  	tbl := NewTable(logger, bgp.RF_IPv4_UC)
    29  
    30  	tbl.setDestination(NewDestination(bgp.NewIPAddrPrefix(23, "11.0.0.0"), 0))
    31  	tbl.setDestination(NewDestination(bgp.NewIPAddrPrefix(24, "11.0.0.0"), 0))
    32  	tbl.setDestination(NewDestination(bgp.NewIPAddrPrefix(32, "11.0.0.4"), 0))
    33  	tbl.setDestination(NewDestination(bgp.NewIPAddrPrefix(32, "11.0.0.129"), 0))
    34  	tbl.setDestination(NewDestination(bgp.NewIPAddrPrefix(28, "11.0.0.144"), 0))
    35  	tbl.setDestination(NewDestination(bgp.NewIPAddrPrefix(29, "11.0.0.144"), 0))
    36  	tbl.setDestination(NewDestination(bgp.NewIPAddrPrefix(32, "11.0.0.145"), 0))
    37  
    38  	r, _ := tbl.GetLongerPrefixDestinations("11.0.0.128/25")
    39  	assert.Equal(t, len(r), 4)
    40  	r, _ = tbl.GetLongerPrefixDestinations("11.0.0.0/24")
    41  	assert.Equal(t, len(r), 6)
    42  }
    43  
    44  func TestTableDeleteDest(t *testing.T) {
    45  	peerT := TableCreatePeer()
    46  	pathT := TableCreatePath(peerT)
    47  	ipv4t := NewTable(logger, bgp.RF_IPv4_UC)
    48  	for _, path := range pathT {
    49  		dest := NewDestination(path.GetNlri(), 0)
    50  		ipv4t.setDestination(dest)
    51  	}
    52  	dest := NewDestination(pathT[0].GetNlri(), 0)
    53  	ipv4t.setDestination(dest)
    54  	ipv4t.deleteDest(dest)
    55  	gdest := ipv4t.GetDestination(pathT[0].GetNlri())
    56  	assert.Nil(t, gdest)
    57  }
    58  
    59  func TestTableGetRouteFamily(t *testing.T) {
    60  	ipv4t := NewTable(logger, bgp.RF_IPv4_UC)
    61  	rf := ipv4t.GetRoutefamily()
    62  	assert.Equal(t, rf, bgp.RF_IPv4_UC)
    63  }
    64  
    65  func TestTableSetDestinations(t *testing.T) {
    66  	peerT := TableCreatePeer()
    67  	pathT := TableCreatePath(peerT)
    68  	ipv4t := NewTable(logger, bgp.RF_IPv4_UC)
    69  	destinations := make(map[string]*Destination)
    70  	for _, path := range pathT {
    71  		tableKey := ipv4t.tableKey(path.GetNlri())
    72  		dest := NewDestination(path.GetNlri(), 0)
    73  		destinations[tableKey] = dest
    74  	}
    75  	ipv4t.setDestinations(destinations)
    76  	ds := ipv4t.GetDestinations()
    77  	assert.Equal(t, ds, destinations)
    78  }
    79  func TestTableGetDestinations(t *testing.T) {
    80  	peerT := DestCreatePeer()
    81  	pathT := DestCreatePath(peerT)
    82  	ipv4t := NewTable(logger, bgp.RF_IPv4_UC)
    83  	destinations := make(map[string]*Destination)
    84  	for _, path := range pathT {
    85  		tableKey := ipv4t.tableKey(path.GetNlri())
    86  		dest := NewDestination(path.GetNlri(), 0)
    87  		destinations[tableKey] = dest
    88  	}
    89  	ipv4t.setDestinations(destinations)
    90  	ds := ipv4t.GetDestinations()
    91  	assert.Equal(t, ds, destinations)
    92  }
    93  
    94  func TestTableKey(t *testing.T) {
    95  	tb := NewTable(logger, bgp.RF_IPv4_UC)
    96  	n1, _ := bgp.NewPrefixFromRouteFamily(bgp.AFI_IP, bgp.SAFI_UNICAST, "0.0.0.0/0")
    97  	d1 := NewDestination(n1, 0)
    98  	n2, _ := bgp.NewPrefixFromRouteFamily(bgp.AFI_IP, bgp.SAFI_UNICAST, "0.0.0.0/1")
    99  	d2 := NewDestination(n2, 0)
   100  	assert.Equal(t, len(tb.tableKey(d1.GetNlri())), 5)
   101  	tb.setDestination(d1)
   102  	tb.setDestination(d2)
   103  	assert.Equal(t, len(tb.GetDestinations()), 2)
   104  }
   105  
   106  func TestTableSelectMalformedIPv4UCPrefixes(t *testing.T) {
   107  	table := NewTable(logger, bgp.RF_IPv4_UC)
   108  	assert.Equal(t, 0, len(table.GetDestinations()))
   109  
   110  	tests := []struct {
   111  		name   string
   112  		prefix string
   113  		option LookupOption
   114  		found  int
   115  	}{
   116  		{
   117  			name:   "Malformed IPv4 Address",
   118  			prefix: "2.2.2.2.2",
   119  			option: LOOKUP_EXACT,
   120  			found:  0,
   121  		},
   122  		{
   123  			name:   "exact match with RD and prefix that does not exist",
   124  			prefix: "foo",
   125  			option: LOOKUP_EXACT,
   126  			found:  0,
   127  		},
   128  	}
   129  
   130  	for _, tt := range tests {
   131  		t.Run(tt.name, func(t *testing.T) {
   132  			filteredTable, _ := table.Select(
   133  				TableSelectOption{
   134  					LookupPrefixes: []*LookupPrefix{{
   135  						Prefix:       tt.prefix,
   136  						LookupOption: tt.option,
   137  					}},
   138  				},
   139  			)
   140  			assert.Equal(t, tt.found, len(filteredTable.GetDestinations()))
   141  		})
   142  	}
   143  }
   144  
   145  func TestTableSelectMalformedIPv6UCPrefixes(t *testing.T) {
   146  	table := NewTable(logger, bgp.RF_IPv6_UC)
   147  	assert.Equal(t, 0, len(table.GetDestinations()))
   148  
   149  	tests := []struct {
   150  		name   string
   151  		prefix string
   152  		option LookupOption
   153  		found  int
   154  	}{
   155  		{
   156  			name:   "Malformed IPv6 Address: 3343:faba:3903:128::::/63",
   157  			prefix: "3343:faba:3903:128::::/63",
   158  			option: LOOKUP_EXACT,
   159  			found:  0,
   160  		},
   161  		{
   162  			name:   "Malformed IPv6 Address: foo",
   163  			prefix: "foo",
   164  			option: LOOKUP_EXACT,
   165  			found:  0,
   166  		},
   167  	}
   168  
   169  	for _, tt := range tests {
   170  		t.Run(tt.name, func(t *testing.T) {
   171  			filteredTable, _ := table.Select(
   172  				TableSelectOption{
   173  					LookupPrefixes: []*LookupPrefix{{
   174  						Prefix:       tt.prefix,
   175  						LookupOption: tt.option,
   176  					}},
   177  				},
   178  			)
   179  			assert.Equal(t, tt.found, len(filteredTable.GetDestinations()))
   180  		})
   181  	}
   182  }
   183  
   184  func TestTableSelectVPNv4(t *testing.T) {
   185  	prefixes := []string{
   186  		"100:100:2.2.2.0/25",
   187  		"100:100:2.2.2.2/32",
   188  		"200:100:2.2.2.2/32",
   189  		"300:100:2.2.2.2/32",
   190  		"100:100:2.2.2.3/32",
   191  		"100:100:2.2.2.4/32",
   192  		"1.1.1.1:1:2.2.2.5/32",
   193  		"8732:1:2.2.2.5/32",
   194  		"8732:1:3.3.3.3/32",
   195  	}
   196  
   197  	table := NewTable(logger, bgp.RF_IPv4_VPN)
   198  	for _, prefix := range prefixes {
   199  		nlri, _ := bgp.NewPrefixFromRouteFamily(bgp.AFI_IP, bgp.SAFI_MPLS_VPN, prefix)
   200  
   201  		destination := NewDestination(nlri, 0, NewPath(nil, nlri, false, nil, time.Now(), false))
   202  		table.setDestination(destination)
   203  	}
   204  	assert.Equal(t, 9, len(table.GetDestinations()))
   205  
   206  	tests := []struct {
   207  		name   string
   208  		prefix string
   209  		RD     string
   210  		option LookupOption
   211  		found  int
   212  	}{
   213  		{
   214  			name:   "exact match with RD that does not exist",
   215  			prefix: "2.2.2.2/32",
   216  			RD:     "500:500",
   217  			option: LOOKUP_EXACT,
   218  			found:  0,
   219  		},
   220  		{
   221  			name:   "exact match with RD and prefix that does not exist",
   222  			prefix: "4.4.4.4/32",
   223  			RD:     "100:100",
   224  			option: LOOKUP_EXACT,
   225  			found:  0,
   226  		},
   227  		{
   228  			name:   "exact match with RD",
   229  			prefix: "2.2.2.0/25",
   230  			RD:     "100:100",
   231  			option: LOOKUP_EXACT,
   232  			found:  1,
   233  		},
   234  		{
   235  			name:   "longer match with RD",
   236  			prefix: "2.2.2.0/25",
   237  			RD:     "100:100",
   238  			option: LOOKUP_LONGER,
   239  			found:  4,
   240  		},
   241  		{
   242  			name:   "shorter match with RD",
   243  			prefix: "2.2.2.2/32",
   244  			RD:     "100:100",
   245  			option: LOOKUP_SHORTER,
   246  			found:  2,
   247  		},
   248  		{
   249  			name:   "exact match without RD for prefix that does not exist",
   250  			prefix: "4.4.4.4/32",
   251  			option: LOOKUP_EXACT,
   252  			found:  0,
   253  		},
   254  		{
   255  			name:   "exact match without RD",
   256  			prefix: "2.2.2.2/32",
   257  			option: LOOKUP_EXACT,
   258  			found:  3,
   259  		},
   260  		{
   261  			name:   "longer match without RD",
   262  			prefix: "2.2.2.0/24",
   263  			option: LOOKUP_LONGER,
   264  			found:  8,
   265  		},
   266  		{
   267  			name:   "shorter match without RD",
   268  			prefix: "2.2.2.2/32",
   269  			option: LOOKUP_SHORTER,
   270  			found:  4,
   271  		},
   272  	}
   273  
   274  	for _, tt := range tests {
   275  		t.Run(tt.name, func(t *testing.T) {
   276  			filteredTable, _ := table.Select(
   277  				TableSelectOption{
   278  					LookupPrefixes: []*LookupPrefix{{
   279  						Prefix:       tt.prefix,
   280  						RD:           tt.RD,
   281  						LookupOption: tt.option,
   282  					}},
   283  				},
   284  			)
   285  			assert.Equal(t, tt.found, len(filteredTable.GetDestinations()))
   286  		})
   287  	}
   288  }
   289  
   290  func TestTableSelectVPNv6(t *testing.T) {
   291  	prefixes := []string{
   292  		"100:100:100::/32",
   293  		"100:100:100::/64",
   294  		"100:100:100:1::/64",
   295  		"100:100:100:2::/64",
   296  		"200:100:100:2::/64",
   297  		"300:100:100:2::/64",
   298  		"100:100:100:3:1::/48",
   299  		"100:100:100:3:1:2::/64",
   300  		"100:100:100:2:3:4:5:6::/96",
   301  	}
   302  
   303  	table := NewTable(logger, bgp.RF_IPv6_VPN)
   304  	for _, prefix := range prefixes {
   305  		nlri, _ := bgp.NewPrefixFromRouteFamily(bgp.AFI_IP6, bgp.SAFI_MPLS_VPN, prefix)
   306  
   307  		destination := NewDestination(nlri, 0, NewPath(nil, nlri, false, nil, time.Now(), false))
   308  		table.setDestination(destination)
   309  	}
   310  	assert.Equal(t, 9, len(table.GetDestinations()))
   311  
   312  	tests := []struct {
   313  		name   string
   314  		prefix string
   315  		RD     string
   316  		option LookupOption
   317  		found  int
   318  	}{
   319  		{
   320  			name:   "exact match with RD that does not exist",
   321  			prefix: "100::/32",
   322  			RD:     "500:500",
   323  			option: LOOKUP_EXACT,
   324  			found:  0,
   325  		},
   326  		{
   327  			name:   "exact match with RD and prefix that does not exist",
   328  			prefix: "200::/32",
   329  			RD:     "100:100",
   330  			option: LOOKUP_EXACT,
   331  			found:  0,
   332  		},
   333  		{
   334  			name:   "exact match with RD",
   335  			prefix: "100:2::/64",
   336  			RD:     "100:100",
   337  			option: LOOKUP_EXACT,
   338  			found:  1,
   339  		},
   340  		{
   341  			name:   "longer match with RD",
   342  			prefix: "100::/16",
   343  			RD:     "100:100",
   344  			option: LOOKUP_LONGER,
   345  			found:  7,
   346  		},
   347  		{
   348  			name:   "shorter match with RD",
   349  			prefix: "100::/96",
   350  			RD:     "100:100",
   351  			option: LOOKUP_SHORTER,
   352  			found:  2,
   353  		},
   354  		{
   355  			name:   "exact match without RD for prefix that does not exist",
   356  			prefix: "100:5::/64",
   357  			option: LOOKUP_EXACT,
   358  			found:  0,
   359  		},
   360  		{
   361  			name:   "exact match without RD",
   362  			prefix: "100:2::/64",
   363  			option: LOOKUP_EXACT,
   364  			found:  3,
   365  		},
   366  		{
   367  			name:   "longer match without RD",
   368  			prefix: "100:3::/32",
   369  			option: LOOKUP_LONGER,
   370  			found:  2,
   371  		},
   372  		{
   373  			name:   "shorter match without RD",
   374  			prefix: "100:2::/96",
   375  			option: LOOKUP_SHORTER,
   376  			found:  3,
   377  		},
   378  	}
   379  
   380  	for _, tt := range tests {
   381  		t.Run(tt.name, func(t *testing.T) {
   382  			filteredTable, _ := table.Select(
   383  				TableSelectOption{
   384  					LookupPrefixes: []*LookupPrefix{{
   385  						Prefix:       tt.prefix,
   386  						RD:           tt.RD,
   387  						LookupOption: tt.option,
   388  					}},
   389  				},
   390  			)
   391  			assert.Equal(t, tt.found, len(filteredTable.GetDestinations()))
   392  		})
   393  	}
   394  }
   395  
   396  func TableCreatePeer() []*PeerInfo {
   397  	peerT1 := &PeerInfo{AS: 65000}
   398  	peerT2 := &PeerInfo{AS: 65001}
   399  	peerT3 := &PeerInfo{AS: 65002}
   400  	peerT := []*PeerInfo{peerT1, peerT2, peerT3}
   401  	return peerT
   402  }
   403  
   404  func TableCreatePath(peerT []*PeerInfo) []*Path {
   405  	bgpMsgT1 := updateMsgT1()
   406  	bgpMsgT2 := updateMsgT2()
   407  	bgpMsgT3 := updateMsgT3()
   408  	pathT := make([]*Path, 3)
   409  	for i, msg := range []*bgp.BGPMessage{bgpMsgT1, bgpMsgT2, bgpMsgT3} {
   410  		updateMsgT := msg.Body.(*bgp.BGPUpdate)
   411  		nlriList := updateMsgT.NLRI
   412  		pathAttributes := updateMsgT.PathAttributes
   413  		nlri_info := nlriList[0]
   414  		pathT[i] = NewPath(peerT[i], nlri_info, false, pathAttributes, time.Now(), false)
   415  	}
   416  	return pathT
   417  }
   418  
   419  func updateMsgT1() *bgp.BGPMessage {
   420  
   421  	origin := bgp.NewPathAttributeOrigin(0)
   422  	aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65000})}
   423  	aspath := bgp.NewPathAttributeAsPath(aspathParam)
   424  	nexthop := bgp.NewPathAttributeNextHop("192.168.50.1")
   425  	med := bgp.NewPathAttributeMultiExitDisc(0)
   426  
   427  	pathAttributes := []bgp.PathAttributeInterface{
   428  		origin,
   429  		aspath,
   430  		nexthop,
   431  		med,
   432  	}
   433  
   434  	nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.10.0")}
   435  	return bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
   436  }
   437  
   438  func updateMsgT2() *bgp.BGPMessage {
   439  
   440  	origin := bgp.NewPathAttributeOrigin(0)
   441  	aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65100})}
   442  	aspath := bgp.NewPathAttributeAsPath(aspathParam)
   443  	nexthop := bgp.NewPathAttributeNextHop("192.168.100.1")
   444  	med := bgp.NewPathAttributeMultiExitDisc(100)
   445  
   446  	pathAttributes := []bgp.PathAttributeInterface{
   447  		origin,
   448  		aspath,
   449  		nexthop,
   450  		med,
   451  	}
   452  
   453  	nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "20.20.20.0")}
   454  	return bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
   455  }
   456  
   457  func updateMsgT3() *bgp.BGPMessage {
   458  	origin := bgp.NewPathAttributeOrigin(0)
   459  	aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65100})}
   460  	aspath := bgp.NewPathAttributeAsPath(aspathParam)
   461  	nexthop := bgp.NewPathAttributeNextHop("192.168.150.1")
   462  	med := bgp.NewPathAttributeMultiExitDisc(100)
   463  
   464  	pathAttributes := []bgp.PathAttributeInterface{
   465  		origin,
   466  		aspath,
   467  		nexthop,
   468  		med,
   469  	}
   470  
   471  	nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "30.30.30.0")}
   472  	w1 := bgp.NewIPAddrPrefix(23, "40.40.40.0")
   473  	withdrawnRoutes := []*bgp.IPAddrPrefix{w1}
   474  	return bgp.NewBGPUpdateMessage(withdrawnRoutes, pathAttributes, nlri)
   475  }