summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--policy/policy.go65
-rw-r--r--policy/policy_test.go409
-rw-r--r--table/path.go58
3 files changed, 468 insertions, 64 deletions
diff --git a/policy/policy.go b/policy/policy.go
index 4f56fab6..49d210aa 100644
--- a/policy/policy.go
+++ b/policy/policy.go
@@ -791,28 +791,29 @@ func (a *CommunityAction) apply(path table.Path) table.Path {
type MedAction struct {
DefaultAction
- Value uint32
+ Value int64
action ActionType
}
const (
MED_ACTION_NONE ActionType = iota
+ MED_ACTION_REPLACE
MED_ACTION_ADD
MED_ACTION_SUB
-// MED_ACTION_IGP
)
-//const (
-// MED_IGP string = "IGP"
-//)
// NewMedAction creates MedAction object.
// If it cannot parse med string, then return nil.
-// Similarly, if option string is invalid, return nil.
func NewMedAction(med config.BgpSetMedType) *MedAction {
+ if med == ""{
+ return nil
+ }
+
m := &MedAction{}
- matched, value, action := getMedValue(fmt.Sprintf("%v", med))
+
+ matched, value, action := getMedValue(fmt.Sprintf("%s", med))
if !matched {
log.WithFields(log.Fields{
"Topic": "Policy",
@@ -826,59 +827,45 @@ func NewMedAction(med config.BgpSetMedType) *MedAction {
}
// getMedValue returns uint32 med value and action type (+ or -).
-// if the string doesn't match a number or operator or well known med name,
-// it returns false and 0 and MED_ACTION_NONE.
-func getMedValue(medStr string) (bool, uint32, ActionType) {
- regUint, _ := regexp.Compile("^([0-9]+)$")
- regUintAc, _ := regexp.Compile("^(\\+|\\-)([0-9]+)$")
-// regIGP, _ := regexp.Compile("^(IGP)$")
- if regUint.MatchString(medStr) {
- val, err := strconv.ParseUint(medStr, 10, 32)
- if err != nil {
- log.WithFields(log.Fields{
- "Topic": "Policy",
- "Type": "Med Action",
- }).Error("failed to parser as number or med value.")
- }
- return true, uint32(val), MED_ACTION_NONE
- }
- if regUintAc.MatchString(medStr) {
- group := regUintAc.FindStringSubmatch(medStr)
- action := MED_ACTION_ADD
- if group[1] == "-" {
+// if the string doesn't match a number or operator,
+// it returns false and 0.
+func getMedValue(medStr string) (bool, int64, ActionType) {
+ regMed, _ := regexp.Compile("^(\\+|\\-)?([0-9]+)$")
+ if regMed.MatchString(medStr) {
+ group := regMed.FindStringSubmatch(medStr)
+ action := MED_ACTION_REPLACE
+ if group[1] == "+" {
+ action = MED_ACTION_ADD
+ } else if group[1] == "-" {
action = MED_ACTION_SUB
}
- val, err := strconv.ParseUint(group[2], 10, 32)
+ val, err := strconv.ParseInt(medStr, 10, 64)
if err != nil {
log.WithFields(log.Fields{
"Topic": "Policy",
"Type": "Med Action",
}).Error("failed to parser as number or med value.")
}
- return true, uint32(val), action
+ return true, int64(val), action
}
-// if regIGP.MatchString(medStr) {
-// return true, uint32(0), MED_IGP
-// }
- return false, uint32(0), MED_ACTION_NONE
+ return false, int64(0), MED_ACTION_NONE
}
-
func (a *MedAction) apply(path table.Path) table.Path {
var err error
switch a.action {
- case MED_ACTION_NONE:
- err = path.SetMed(a.Value, true, false)
+ case MED_ACTION_REPLACE:
+ err = path.SetMed(a.Value, true)
case MED_ACTION_ADD:
- err = path.SetMed(a.Value, false, false)
+ err = path.SetMed(a.Value, false)
case MED_ACTION_SUB:
- err = path.SetMed(a.Value, false, true)
+ err = path.SetMed(a.Value, false)
}
if err != nil {
log.WithFields(log.Fields{
"Topic": "Policy",
"Type": "Med Action",
- }).Error(err)
+ }).Warn(err)
}
return path
diff --git a/policy/policy_test.go b/policy/policy_test.go
index 2eced491..ebabb3c8 100644
--- a/policy/policy_test.go
+++ b/policy/policy_test.go
@@ -25,6 +25,8 @@ import (
"strconv"
"strings"
"testing"
+ "fmt"
+ "math"
)
func TestPrefixCalcurateNoRange(t *testing.T) {
@@ -1441,4 +1443,409 @@ func stringToCommunityValue(comStr string) uint32 {
asn, _ := strconv.ParseUint(elem[0], 10, 16)
val, _ := strconv.ParseUint(elem[1], 10, 16)
return uint32(asn<<16 | val)
-} \ No newline at end of file
+}
+
+func TestPolicyMatchAndReplaceMed(t *testing.T) {
+
+ // create path
+ peer := &table.PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
+ origin := bgp.NewPathAttributeOrigin(0)
+ aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})}
+ aspath := bgp.NewPathAttributeAsPath(aspathParam)
+ nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
+ med := bgp.NewPathAttributeMultiExitDisc(100)
+
+ pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med}
+ nlri := []bgp.NLRInfo{*bgp.NewNLRInfo(24, "10.10.0.101")}
+ withdrawnRoutes := []bgp.WithdrawnRoute{}
+ updateMsg := bgp.NewBGPUpdateMessage(withdrawnRoutes, pathAttributes, nlri)
+ path := table.ProcessMessage(updateMsg, peer)[0]
+ // create policy
+ ps := config.PrefixSet{
+ PrefixSetName: "ps1",
+ PrefixList: []config.Prefix{
+ config.Prefix{
+ Address: net.ParseIP("10.10.0.0"),
+ Masklength: 16,
+ MasklengthRange: "21..24",
+ }},
+ }
+ ns := config.NeighborSet{
+ NeighborSetName: "ns1",
+ NeighborInfoList: []config.NeighborInfo{
+ config.NeighborInfo{
+ Address: net.ParseIP("10.0.0.1"),
+ }},
+ }
+ ds := config.DefinedSets{
+ PrefixSetList: []config.PrefixSet{ps},
+ NeighborSetList: []config.NeighborSet{ns},
+ }
+
+ m := "200"
+ s := config.Statement{
+ Name: "statement1",
+ Conditions: config.Conditions{
+ MatchPrefixSet: "ps1",
+ MatchNeighborSet: "ns1",
+ MatchSetOptions: config.MATCH_SET_OPTIONS_TYPE_ALL,
+ },
+ Actions: config.Actions{
+ AcceptRoute: true,
+ BgpActions: config.BgpActions{
+ SetMed: config.BgpSetMedType(m),
+ },
+ },
+ }
+
+ pd := config.PolicyDefinition{"pd1", []config.Statement{s}}
+ pl := config.RoutingPolicy{ds, []config.PolicyDefinition{pd}}
+ //test
+ df := pl.DefinedSets
+ p := NewPolicy(pl.PolicyDefinitionList[0], df)
+ match, pType, newPath := p.Apply(path)
+ assert.Equal(t, true, match)
+ assert.Equal(t, ROUTE_TYPE_ACCEPT, pType)
+ assert.NotEqual(t, nil, newPath)
+
+ newMed := fmt.Sprintf("%d", newPath.GetMed())
+ assert.Equal(t, m, newMed)
+}
+
+func TestPolicyMatchAndAddingMed(t *testing.T) {
+
+ // create path
+ peer := &table.PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
+ origin := bgp.NewPathAttributeOrigin(0)
+ aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})}
+ aspath := bgp.NewPathAttributeAsPath(aspathParam)
+ nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
+ med := bgp.NewPathAttributeMultiExitDisc(100)
+
+ pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med}
+ nlri := []bgp.NLRInfo{*bgp.NewNLRInfo(24, "10.10.0.101")}
+ withdrawnRoutes := []bgp.WithdrawnRoute{}
+ updateMsg := bgp.NewBGPUpdateMessage(withdrawnRoutes, pathAttributes, nlri)
+ path := table.ProcessMessage(updateMsg, peer)[0]
+ // create policy
+ ps := config.PrefixSet{
+ PrefixSetName: "ps1",
+ PrefixList: []config.Prefix{
+ config.Prefix{
+ Address: net.ParseIP("10.10.0.0"),
+ Masklength: 16,
+ MasklengthRange: "21..24",
+ }},
+ }
+ ns := config.NeighborSet{
+ NeighborSetName: "ns1",
+ NeighborInfoList: []config.NeighborInfo{
+ config.NeighborInfo{
+ Address: net.ParseIP("10.0.0.1"),
+ }},
+ }
+ ds := config.DefinedSets{
+ PrefixSetList: []config.PrefixSet{ps},
+ NeighborSetList: []config.NeighborSet{ns},
+ }
+
+ m := "+200"
+ ma := "300"
+ s := config.Statement{
+ Name: "statement1",
+ Conditions: config.Conditions{
+ MatchPrefixSet: "ps1",
+ MatchNeighborSet: "ns1",
+ MatchSetOptions: config.MATCH_SET_OPTIONS_TYPE_ALL,
+ },
+ Actions: config.Actions{
+ AcceptRoute: true,
+ BgpActions: config.BgpActions{
+ SetMed: config.BgpSetMedType(m),
+ },
+ },
+ }
+
+ pd := config.PolicyDefinition{"pd1", []config.Statement{s}}
+ pl := config.RoutingPolicy{ds, []config.PolicyDefinition{pd}}
+ //test
+ df := pl.DefinedSets
+ p := NewPolicy(pl.PolicyDefinitionList[0], df)
+ match, pType, newPath := p.Apply(path)
+ assert.Equal(t, true, match)
+ assert.Equal(t, ROUTE_TYPE_ACCEPT, pType)
+ assert.NotEqual(t, nil, newPath)
+
+ newMed := fmt.Sprintf("%d", newPath.GetMed())
+ assert.Equal(t, ma, newMed)
+}
+
+func TestPolicyMatchAndAddingMedOverFlow(t *testing.T) {
+
+ // create path
+ peer := &table.PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
+ origin := bgp.NewPathAttributeOrigin(0)
+ aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})}
+ aspath := bgp.NewPathAttributeAsPath(aspathParam)
+ nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
+ med := bgp.NewPathAttributeMultiExitDisc(1)
+
+ pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med}
+ nlri := []bgp.NLRInfo{*bgp.NewNLRInfo(24, "10.10.0.101")}
+ withdrawnRoutes := []bgp.WithdrawnRoute{}
+ updateMsg := bgp.NewBGPUpdateMessage(withdrawnRoutes, pathAttributes, nlri)
+ path := table.ProcessMessage(updateMsg, peer)[0]
+ // create policy
+ ps := config.PrefixSet{
+ PrefixSetName: "ps1",
+ PrefixList: []config.Prefix{
+ config.Prefix{
+ Address: net.ParseIP("10.10.0.0"),
+ Masklength: 16,
+ MasklengthRange: "21..24",
+ }},
+ }
+ ns := config.NeighborSet{
+ NeighborSetName: "ns1",
+ NeighborInfoList: []config.NeighborInfo{
+ config.NeighborInfo{
+ Address: net.ParseIP("10.0.0.1"),
+ }},
+ }
+ ds := config.DefinedSets{
+ PrefixSetList: []config.PrefixSet{ps},
+ NeighborSetList: []config.NeighborSet{ns},
+ }
+
+ m := fmt.Sprintf("+%d",math.MaxUint32)
+ ma := "1"
+ s := config.Statement{
+ Name: "statement1",
+ Conditions: config.Conditions{
+ MatchPrefixSet: "ps1",
+ MatchNeighborSet: "ns1",
+ MatchSetOptions: config.MATCH_SET_OPTIONS_TYPE_ALL,
+ },
+ Actions: config.Actions{
+ AcceptRoute: true,
+ BgpActions: config.BgpActions{
+ SetMed: config.BgpSetMedType(m),
+ },
+ },
+ }
+
+ pd := config.PolicyDefinition{"pd1", []config.Statement{s}}
+ pl := config.RoutingPolicy{ds, []config.PolicyDefinition{pd}}
+ //test
+ df := pl.DefinedSets
+ p := NewPolicy(pl.PolicyDefinitionList[0], df)
+ match, pType, newPath := p.Apply(path)
+ assert.Equal(t, true, match)
+ assert.Equal(t, ROUTE_TYPE_ACCEPT, pType)
+ assert.NotEqual(t, nil, newPath)
+
+ newMed := fmt.Sprintf("%d", newPath.GetMed())
+ assert.Equal(t, ma, newMed)
+}
+
+func TestPolicyMatchAndSubtractMed(t *testing.T) {
+
+ // create path
+ peer := &table.PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
+ origin := bgp.NewPathAttributeOrigin(0)
+ aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})}
+ aspath := bgp.NewPathAttributeAsPath(aspathParam)
+ nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
+ med := bgp.NewPathAttributeMultiExitDisc(100)
+
+ pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med}
+ nlri := []bgp.NLRInfo{*bgp.NewNLRInfo(24, "10.10.0.101")}
+ withdrawnRoutes := []bgp.WithdrawnRoute{}
+ updateMsg := bgp.NewBGPUpdateMessage(withdrawnRoutes, pathAttributes, nlri)
+ path := table.ProcessMessage(updateMsg, peer)[0]
+ // create policy
+ ps := config.PrefixSet{
+ PrefixSetName: "ps1",
+ PrefixList: []config.Prefix{
+ config.Prefix{
+ Address: net.ParseIP("10.10.0.0"),
+ Masklength: 16,
+ MasklengthRange: "21..24",
+ }},
+ }
+ ns := config.NeighborSet{
+ NeighborSetName: "ns1",
+ NeighborInfoList: []config.NeighborInfo{
+ config.NeighborInfo{
+ Address: net.ParseIP("10.0.0.1"),
+ }},
+ }
+ ds := config.DefinedSets{
+ PrefixSetList: []config.PrefixSet{ps},
+ NeighborSetList: []config.NeighborSet{ns},
+ }
+
+ m := "-50"
+ ma := "50"
+ s := config.Statement{
+ Name: "statement1",
+ Conditions: config.Conditions{
+ MatchPrefixSet: "ps1",
+ MatchNeighborSet: "ns1",
+ MatchSetOptions: config.MATCH_SET_OPTIONS_TYPE_ALL,
+ },
+ Actions: config.Actions{
+ AcceptRoute: true,
+ BgpActions: config.BgpActions{
+ SetMed: config.BgpSetMedType(m),
+ },
+ },
+ }
+
+ pd := config.PolicyDefinition{"pd1", []config.Statement{s}}
+ pl := config.RoutingPolicy{ds, []config.PolicyDefinition{pd}}
+ //test
+ df := pl.DefinedSets
+ p := NewPolicy(pl.PolicyDefinitionList[0], df)
+ match, pType, newPath := p.Apply(path)
+ assert.Equal(t, true, match)
+ assert.Equal(t, ROUTE_TYPE_ACCEPT, pType)
+ assert.NotEqual(t, nil, newPath)
+
+ newMed := fmt.Sprintf("%d", newPath.GetMed())
+ assert.Equal(t, ma, newMed)
+}
+
+func TestPolicyMatchAndSubtractMedUnderFlow(t *testing.T) {
+
+ // create path
+ peer := &table.PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
+ origin := bgp.NewPathAttributeOrigin(0)
+ aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})}
+ aspath := bgp.NewPathAttributeAsPath(aspathParam)
+ nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
+ med := bgp.NewPathAttributeMultiExitDisc(100)
+
+ pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med}
+ nlri := []bgp.NLRInfo{*bgp.NewNLRInfo(24, "10.10.0.101")}
+ withdrawnRoutes := []bgp.WithdrawnRoute{}
+ updateMsg := bgp.NewBGPUpdateMessage(withdrawnRoutes, pathAttributes, nlri)
+ path := table.ProcessMessage(updateMsg, peer)[0]
+ // create policy
+ ps := config.PrefixSet{
+ PrefixSetName: "ps1",
+ PrefixList: []config.Prefix{
+ config.Prefix{
+ Address: net.ParseIP("10.10.0.0"),
+ Masklength: 16,
+ MasklengthRange: "21..24",
+ }},
+ }
+ ns := config.NeighborSet{
+ NeighborSetName: "ns1",
+ NeighborInfoList: []config.NeighborInfo{
+ config.NeighborInfo{
+ Address: net.ParseIP("10.0.0.1"),
+ }},
+ }
+ ds := config.DefinedSets{
+ PrefixSetList: []config.PrefixSet{ps},
+ NeighborSetList: []config.NeighborSet{ns},
+ }
+
+ m := "-101"
+ ma := "100"
+ s := config.Statement{
+ Name: "statement1",
+ Conditions: config.Conditions{
+ MatchPrefixSet: "ps1",
+ MatchNeighborSet: "ns1",
+ MatchSetOptions: config.MATCH_SET_OPTIONS_TYPE_ALL,
+ },
+ Actions: config.Actions{
+ AcceptRoute: true,
+ BgpActions: config.BgpActions{
+ SetMed: config.BgpSetMedType(m),
+ },
+ },
+ }
+
+ pd := config.PolicyDefinition{"pd1", []config.Statement{s}}
+ pl := config.RoutingPolicy{ds, []config.PolicyDefinition{pd}}
+ //test
+ df := pl.DefinedSets
+ p := NewPolicy(pl.PolicyDefinitionList[0], df)
+ match, pType, newPath := p.Apply(path)
+ assert.Equal(t, true, match)
+ assert.Equal(t, ROUTE_TYPE_ACCEPT, pType)
+ assert.NotEqual(t, nil, newPath)
+
+ newMed := fmt.Sprintf("%d", newPath.GetMed())
+ assert.Equal(t, ma, newMed)
+}
+
+func TestPolicyMatchWhenPathHaveNotMed(t *testing.T) {
+
+ // create path
+ peer := &table.PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
+ origin := bgp.NewPathAttributeOrigin(0)
+ aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})}
+ aspath := bgp.NewPathAttributeAsPath(aspathParam)
+ nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
+
+ pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop}
+ nlri := []bgp.NLRInfo{*bgp.NewNLRInfo(24, "10.10.0.101")}
+ withdrawnRoutes := []bgp.WithdrawnRoute{}
+ updateMsg := bgp.NewBGPUpdateMessage(withdrawnRoutes, pathAttributes, nlri)
+ path := table.ProcessMessage(updateMsg, peer)[0]
+ // create policy
+ ps := config.PrefixSet{
+ PrefixSetName: "ps1",
+ PrefixList: []config.Prefix{
+ config.Prefix{
+ Address: net.ParseIP("10.10.0.0"),
+ Masklength: 16,
+ MasklengthRange: "21..24",
+ }},
+ }
+ ns := config.NeighborSet{
+ NeighborSetName: "ns1",
+ NeighborInfoList: []config.NeighborInfo{
+ config.NeighborInfo{
+ Address: net.ParseIP("10.0.0.1"),
+ }},
+ }
+ ds := config.DefinedSets{
+ PrefixSetList: []config.PrefixSet{ps},
+ NeighborSetList: []config.NeighborSet{ns},
+ }
+
+ m := "-50"
+ s := config.Statement{
+ Name: "statement1",
+ Conditions: config.Conditions{
+ MatchPrefixSet: "ps1",
+ MatchNeighborSet: "ns1",
+ MatchSetOptions: config.MATCH_SET_OPTIONS_TYPE_ALL,
+ },
+ Actions: config.Actions{
+ AcceptRoute: true,
+ BgpActions: config.BgpActions{
+ SetMed: config.BgpSetMedType(m),
+ },
+ },
+ }
+
+ pd := config.PolicyDefinition{"pd1", []config.Statement{s}}
+ pl := config.RoutingPolicy{ds, []config.PolicyDefinition{pd}}
+ //test
+ df := pl.DefinedSets
+ p := NewPolicy(pl.PolicyDefinitionList[0], df)
+ match, pType, newPath := p.Apply(path)
+ assert.Equal(t, true, match)
+ assert.Equal(t, ROUTE_TYPE_ACCEPT, pType)
+ assert.NotEqual(t, nil, newPath)
+
+ newMed := fmt.Sprintf("%d", newPath.GetMed())
+ assert.Equal(t, "0", newMed)
+}
diff --git a/table/path.go b/table/path.go
index a82c5e59..390d5f1d 100644
--- a/table/path.go
+++ b/table/path.go
@@ -41,7 +41,8 @@ type Path interface {
SetCommunities([]uint32, bool)
RemoveCommunities([]uint32) int
ClearCommunities()
- SetMed(uint32, bool, bool) error
+ GetMed() uint32
+ SetMed(int64, bool) error
setSource(source *PeerInfo)
GetSource() *PeerInfo
GetSourceAs() uint32
@@ -481,37 +482,46 @@ func (pd *PathDefault) ClearCommunities() {
}
}
+func (pd *PathDefault) GetMed() uint32 {
+ _, attr := pd.getPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC)
+ med := attr.(*bgp.PathAttributeMultiExitDisc).Value
+ return med
+}
+
// SetMed replace, add or subtraction med with new ones.
-func (pd *PathDefault) SetMed(med uint32, doReplace bool, doSubstruction bool) error {
- newMed := &bgp.PathAttributeMultiExitDisc{}
- idx, attr := pd.getPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC)
- if attr != nil{
- m := attr.(*bgp.PathAttributeMultiExitDisc)
+func (pd *PathDefault) SetMed(med int64, doReplace bool) error {
+
+ parseMed := func(orgMed uint32, med int64, doReplace bool) (*bgp.PathAttributeMultiExitDisc, error) {
+ newMed := &bgp.PathAttributeMultiExitDisc{}
if doReplace {
- newMed = bgp.NewPathAttributeMultiExitDisc(med)
+ newMed = bgp.NewPathAttributeMultiExitDisc(uint32(med))
} else {
- if doSubstruction {
- if m.Value - med < 0 {
- return fmt.Errorf("med value invalid. the underflow threshold")
- }
- newMed = bgp.NewPathAttributeMultiExitDisc(m.Value - med)
- } else {
- if m.Value + med > math.MaxUint32 {
- return fmt.Errorf("med value invalid. the overflow threshold")
- }
- newMed = bgp.NewPathAttributeMultiExitDisc(m.Value + med)
+ if int64(orgMed) + med < 0 {
+ return nil, fmt.Errorf("med value invalid. it's underflow threshold.")
+ } else if int64(orgMed) + med > int64(math.MaxUint32) {
+ return nil, fmt.Errorf("med value invalid. it's overflow threshold.")
}
+ newMed = bgp.NewPathAttributeMultiExitDisc(uint32(int64(orgMed) + med))
+ }
+ return newMed, nil
+ }
+
+ idx, attr := pd.getPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC)
+ if attr != nil{
+ m := attr.(*bgp.PathAttributeMultiExitDisc)
+ newMed, err := parseMed(m.Value, med, doReplace)
+ if err != nil{
+ return err
}
pd.pathAttrs[idx] = newMed
} else {
- if doReplace {
- newMed = bgp.NewPathAttributeMultiExitDisc(med)
- } else {
- if !doSubstruction {
- newMed = bgp.NewPathAttributeMultiExitDisc(med)
- }
+ m := 0
+ newMed, err := parseMed(uint32(m), med, doReplace)
+ if err != nil{
+ pd.pathAttrs = append(pd.pathAttrs, &bgp.PathAttributeMultiExitDisc{})
+ return err
}
- pd.pathAttrs[idx] = newMed
+ pd.pathAttrs = append(pd.pathAttrs, newMed)
}
return nil
}