Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions charts/kube-ovn-v2/crds/kube-ovn-crd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2361,6 +2361,11 @@ spec:
type: string
nextHopIP:
type: string
externalIDs:
type: object
additionalProperties:
type: string
description: Custom metadata key-value pairs. The "vendor" key is reserved.
type: object
type: array
vpcPeerings:
Expand Down
5 changes: 5 additions & 0 deletions charts/kube-ovn/templates/kube-ovn-crd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2362,6 +2362,11 @@ spec:
type: string
nextHopIP:
type: string
externalIDs:
type: object
additionalProperties:
type: string
description: Custom metadata key-value pairs. The "vendor" key is reserved.
type: object
type: array
vpcPeerings:
Expand Down
5 changes: 5 additions & 0 deletions dist/images/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2612,6 +2612,11 @@ spec:
type: string
nextHopIP:
type: string
externalIDs:
type: object
additionalProperties:
type: string
description: Custom metadata key-value pairs. The "vendor" key is reserved.
type: object
type: array
vpcPeerings:
Expand Down
4 changes: 4 additions & 0 deletions pkg/apis/kubeovn/v1/vpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ type PolicyRoute struct {
// NextHopIP is an optional parameter. It needs to be provided only when 'action' is 'reroute'.
// +optional
NextHopIP string `json:"nextHopIP,omitempty"`
// ExternalIDs is an optional parameter for custom metadata.
// The "vendor" key is reserved and will always be set to "kube-ovn".
// +optional
ExternalIDs map[string]string `json:"externalIDs,omitempty"`
}

type BFDPortStatus struct {
Expand Down
14 changes: 13 additions & 1 deletion pkg/apis/kubeovn/v1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

61 changes: 44 additions & 17 deletions pkg/controller/vpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -532,11 +532,13 @@ func (c *Controller) handleAddOrUpdateVpc(key string) error {
return err
}
}
// add new policies
// add new policies or update existing ones with changed externalIDs
for _, item := range policyRouteNeedAdd {
klog.Infof("add policy route for router: %s, match %s, action %s, nexthop %s, externalID %v", c.config.ClusterRouter, item.Match, string(item.Action), item.NextHopIP, externalIDs)
if err = c.OVNNbClient.AddLogicalRouterPolicy(vpc.Name, item.Priority, item.Match, string(item.Action), []string{item.NextHopIP}, nil, externalIDs); err != nil {
klog.Errorf("add policy route to vpc %s failed, %v", vpc.Name, err)
mergedExternalIDs := mergeExternalIDs(item.ExternalIDs)

klog.Infof("apply policy route for router: %s, match %s, action %s, nexthop %s, externalID %v", vpc.Name, item.Match, string(item.Action), item.NextHopIP, mergedExternalIDs)
if err = c.OVNNbClient.AddLogicalRouterPolicy(vpc.Name, item.Priority, item.Match, string(item.Action), []string{item.NextHopIP}, nil, mergedExternalIDs); err != nil {
klog.Errorf("failed to apply policy route to vpc %s, %v", vpc.Name, err)
return err
}
}
Expand Down Expand Up @@ -1032,19 +1034,22 @@ func diffPolicyRouteWithExisted(exists, target []*kubeovnv1.PolicyRoute) ([]*kub
dels, adds []*kubeovnv1.PolicyRoute
existsMap map[string]*kubeovnv1.PolicyRoute
key string
ok bool
)

existsMap = make(map[string]*kubeovnv1.PolicyRoute, len(exists))
for _, item := range exists {
existsMap[getPolicyRouteItemKey(item)] = item
}
// load policies to add
// load policies to add or update
for _, item := range target {
key = getPolicyRouteItemKey(item)

if _, ok = existsMap[key]; ok {
if existing, ok := existsMap[key]; ok {
delete(existsMap, key)
// Check if externalIDs changed, if so, add to adds list for upsert
if !maps.Equal(mergeExternalIDs(existing.ExternalIDs), mergeExternalIDs(item.ExternalIDs)) {
adds = append(adds, item)
}
} else {
adds = append(adds, item)
}
Expand All @@ -1056,36 +1061,49 @@ func diffPolicyRouteWithExisted(exists, target []*kubeovnv1.PolicyRoute) ([]*kub
return dels, adds
}

// policyRouteLogicalInfo holds both the K8s PolicyRoute representation and the original OVN policy's ExternalIDs
type policyRouteLogicalInfo struct {
route *kubeovnv1.PolicyRoute
externalIDs map[string]string
}

func diffPolicyRouteWithLogical(exists []*ovnnb.LogicalRouterPolicy, target []*kubeovnv1.PolicyRoute) ([]*kubeovnv1.PolicyRoute, []*kubeovnv1.PolicyRoute) {
var (
dels, adds []*kubeovnv1.PolicyRoute
existsMap map[string]*kubeovnv1.PolicyRoute
existsMap map[string]*policyRouteLogicalInfo
key string
ok bool
)
existsMap = make(map[string]*kubeovnv1.PolicyRoute, len(exists))
existsMap = make(map[string]*policyRouteLogicalInfo, len(exists))

for _, item := range exists {
policy := &kubeovnv1.PolicyRoute{
Priority: item.Priority,
Match: item.Match,
Action: kubeovnv1.PolicyRouteAction(item.Action),
Priority: item.Priority,
Match: item.Match,
Action: kubeovnv1.PolicyRouteAction(item.Action),
NextHopIP: strings.Join(item.Nexthops, ","),
}
existsMap[getPolicyRouteItemKey(policy)] = &policyRouteLogicalInfo{
route: policy,
externalIDs: item.ExternalIDs,
}
existsMap[getPolicyRouteItemKey(policy)] = policy
}

for _, item := range target {
key = getPolicyRouteItemKey(item)

if _, ok = existsMap[key]; ok {
if existing, ok := existsMap[key]; ok {
delete(existsMap, key)
// Check if externalIDs changed, if so, add to adds list for upsert
if !maps.Equal(existing.externalIDs, mergeExternalIDs(item.ExternalIDs)) {
adds = append(adds, item)
}
} else {
adds = append(adds, item)
}
}

for _, item := range existsMap {
dels = append(dels, item)
for _, info := range existsMap {
dels = append(dels, info.route)
}
return dels, adds
}
Expand All @@ -1094,6 +1112,15 @@ func getPolicyRouteItemKey(item *kubeovnv1.PolicyRoute) (key string) {
return fmt.Sprintf("%d:%s:%s:%s", item.Priority, item.Match, item.Action, item.NextHopIP)
}

// mergeExternalIDs merges user-specified externalIDs with the default vendor key.
// The vendor key is always set to util.CniTypeName to prevent user override.
func mergeExternalIDs(externalIDs map[string]string) map[string]string {
merged := make(map[string]string, len(externalIDs)+1)
maps.Copy(merged, externalIDs)
merged["vendor"] = util.CniTypeName
return merged
}

func diffStaticRoute(exist []*ovnnb.LogicalRouterStaticRoute, target []*kubeovnv1.StaticRoute) (routeNeedDel, routeNeedAdd []*kubeovnv1.StaticRoute, err error) {
existRouteMap := make(map[string]*kubeovnv1.StaticRoute, len(exist))
for _, item := range exist {
Expand Down
Loading
Loading