Skip to content

Commit

Permalink
feature: vpc support policy route
Browse files Browse the repository at this point in the history
  • Loading branch information
luoyunhe committed Sep 14, 2021
1 parent 6803527 commit 871c149
Show file tree
Hide file tree
Showing 9 changed files with 255 additions and 8 deletions.
13 changes: 13 additions & 0 deletions dist/images/install-pre-1.16.sh
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,19 @@ spec:
type: string
type: object
type: array
policyRoutes:
items:
properties:
priority:
type: integer
action:
type: string
match:
type: string
nextHopIP:
type: string
type: object
type: array
type: object
status:
properties:
Expand Down
13 changes: 13 additions & 0 deletions dist/images/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,19 @@ spec:
type: string
type: object
type: array
policyRoutes:
items:
properties:
priority:
type: integer
action:
type: string
match:
type: string
nextHopIP:
type: string
type: object
type: array
type: object
status:
properties:
Expand Down
18 changes: 18 additions & 0 deletions pkg/apis/kubeovn/v1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,7 @@ type Vpc struct {
type VpcSpec struct {
Namespaces []string `json:"namespaces,omitempty"`
StaticRoutes []*StaticRoute `json:"staticRoutes,omitempty"`
PolicyRoutes []*PolicyRoute `json:"policyRoutes,omitempty"`
}

type RoutePolicy string
Expand All @@ -341,6 +342,23 @@ type StaticRoute struct {
NextHopIP string `json:"nextHopIP"`
}

type PolicyRouteAction string

const (
PolicyRouteActionAllow PolicyRouteAction = "allow"
PolicyRouteActionDrop PolicyRouteAction = "drop"
PolicyRouteActionReroute PolicyRouteAction = "reroute"
)

type PolicyRoute struct {
Priority int32 `json:"priority,omitempty"`
Match string `json:"match,omitempty"`
Action PolicyRouteAction `json:"action,omitempty"`
// NextHopIP is an optional parameter. It needs to be provided only when 'action' is 'reroute'.
// +optional
NextHopIP string `json:"nextHopIP,omitempty"`
}

type VpcStatus struct {
// Conditions represents the latest state of the object
// +optional
Expand Down
27 changes: 27 additions & 0 deletions 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.

82 changes: 75 additions & 7 deletions pkg/controller/vpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -265,14 +265,14 @@ func (c *Controller) handleAddOrUpdateVpc(key string) error {
}

if vpc.Name != util.DefaultVpc {
// handle route
// handle static route
existRoute, err := c.ovnClient.GetStaticRouteList(vpc.Name)
if err != nil {
klog.Errorf("failed to get vpc %s static route list, %v", vpc.Name, err)
return err
}

routeNeedDel, routeNeedAdd, err := diffRoute(existRoute, vpc.Spec.StaticRoutes)
routeNeedDel, routeNeedAdd, err := diffStaticRoute(existRoute, vpc.Spec.StaticRoutes)
if err != nil {
klog.Errorf("failed to diff vpc %s static route, %v", vpc.Name, err)
return err
Expand All @@ -290,6 +290,30 @@ func (c *Controller) handleAddOrUpdateVpc(key string) error {
return err
}
}
// handle policy route
existPolicyRoute, err := c.ovnClient.GetPolicyRouteList(vpc.Name)
if err != nil {
klog.Errorf("failed to get vpc %s policy route list, %v", vpc.Name, err)
return err
}

policyRouteNeedDel, policyRouteNeedAdd, err := diffPolicyRoute(existPolicyRoute, vpc.Spec.PolicyRoutes)
if err != nil {
klog.Errorf("failed to diff vpc %s policy route, %v", vpc.Name, err)
return err
}
for _, item := range policyRouteNeedDel {
if err = c.ovnClient.DeletePolicyRoute(vpc.Name, item.Priority, item.Match); err != nil {
klog.Errorf("del vpc %s policy route failed, %v", vpc.Name, err)
return err
}
}
for _, item := range policyRouteNeedAdd {
if err = c.ovnClient.AddPolicyRoute(vpc.Name, item.Priority, item.Match, string(item.Action), item.NextHopIP); err != nil {
klog.Errorf("add policy route to vpc %s failed, %v", vpc.Name, err)
return err
}
}
}

vpc.Status.Router = key
Expand All @@ -315,7 +339,41 @@ func (c *Controller) handleAddOrUpdateVpc(key string) error {
return nil
}

func diffRoute(exist []*ovs.StaticRoute, target []*kubeovnv1.StaticRoute) (routeNeedDel []*kubeovnv1.StaticRoute, routeNeedAdd []*kubeovnv1.StaticRoute, err error) {
func diffPolicyRoute(exist []*ovs.PolicyRoute, target []*kubeovnv1.PolicyRoute) (routeNeedDel []*kubeovnv1.PolicyRoute, routeNeedAdd []*kubeovnv1.PolicyRoute, err error) {
existV1 := make([]*kubeovnv1.PolicyRoute, 0, len(exist))
for _, item := range exist {
existV1 = append(existV1, &kubeovnv1.PolicyRoute{
Priority: item.Priority,
Match: item.Match,
Action: kubeovnv1.PolicyRouteAction(item.Action),
NextHopIP: item.NextHopIP,
})
}

existRouteMap := make(map[string]*kubeovnv1.PolicyRoute, len(exist))
for _, item := range existV1 {
existRouteMap[getPolicyRouteItemKey(item)] = item
}

for _, item := range target {
key := getPolicyRouteItemKey(item)
if _, ok := existRouteMap[key]; ok {
delete(existRouteMap, key)
} else {
routeNeedAdd = append(routeNeedAdd, item)
}
}
for _, item := range existRouteMap {
routeNeedDel = append(routeNeedDel, item)
}
return routeNeedDel, routeNeedAdd, nil
}

func getPolicyRouteItemKey(item *kubeovnv1.PolicyRoute) (key string) {
return fmt.Sprintf("%d:%s:%s:%s", item.Priority, item.Match, item.Action, item.NextHopIP)
}

func diffStaticRoute(exist []*ovs.StaticRoute, target []*kubeovnv1.StaticRoute) (routeNeedDel []*kubeovnv1.StaticRoute, routeNeedAdd []*kubeovnv1.StaticRoute, err error) {
existV1 := make([]*kubeovnv1.StaticRoute, 0, len(exist))
for _, item := range exist {
policy := kubeovnv1.PolicyDst
Expand All @@ -331,11 +389,11 @@ func diffRoute(exist []*ovs.StaticRoute, target []*kubeovnv1.StaticRoute) (route

existRouteMap := make(map[string]*kubeovnv1.StaticRoute, len(exist))
for _, item := range existV1 {
existRouteMap[getRouteItemKey(item)] = item
existRouteMap[getStaticRouteItemKey(item)] = item
}

for _, item := range target {
key := getRouteItemKey(item)
key := getStaticRouteItemKey(item)
if _, ok := existRouteMap[key]; ok {
delete(existRouteMap, key)
} else {
Expand All @@ -348,7 +406,7 @@ func diffRoute(exist []*ovs.StaticRoute, target []*kubeovnv1.StaticRoute) (route
return
}

func getRouteItemKey(item *kubeovnv1.StaticRoute) (key string) {
func getStaticRouteItemKey(item *kubeovnv1.StaticRoute) (key string) {
if item.Policy == kubeovnv1.PolicyDst {
return fmt.Sprintf("dst:%s=>%s", item.CIDR, item.NextHopIP)
} else {
Expand Down Expand Up @@ -390,6 +448,16 @@ func formatVpc(vpc *kubeovnv1.Vpc, c *Controller) (err error) {
}

}

for _, route := range vpc.Spec.PolicyRoutes {
if route.Action != kubeovnv1.PolicyRouteActionReroute {
route.NextHopIP = ""
} else {
if ip := net.ParseIP(route.NextHopIP); ip == nil {
return fmt.Errorf("bad next hop ip: %s, err: %w", route.NextHopIP, err)
}
}
}
}
if changed {
if _, err = c.config.KubeOvnClient.KubeovnV1().Vpcs().Update(context.Background(), vpc, metav1.UpdateOptions{}); err != nil {
Expand Down Expand Up @@ -454,7 +522,7 @@ func (c *Controller) processNextAddVpcWorkItem() bool {
return nil
}
if err := c.handleAddOrUpdateVpc(key); err != nil {
//c.addOrUpdateVpcQueue.AddRateLimited(key)
// c.addOrUpdateVpcQueue.AddRateLimited(key)
return fmt.Errorf("error syncing '%s': %s, requeuing", key, err.Error())
}
c.addOrUpdateVpcQueue.Forget(obj)
Expand Down
72 changes: 71 additions & 1 deletion pkg/ovs/ovn-nbctl.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ func (c Client) SetPortExternalIds(port, key, value string) error {
func (c Client) CreatePort(ls, port, ip, cidr, mac, pod, namespace string, portSecurity bool, securityGroups string) error {
var ovnCommand []string
if util.CheckProtocol(cidr) == kubeovnv1.ProtocolDual {
//ips := strings.Split(ip, ",")
// ips := strings.Split(ip, ",")
ovnCommand = []string{MayExist, "lsp-add", ls, port, "--",
"lsp-set-addresses", port, mac}

Expand Down Expand Up @@ -715,6 +715,76 @@ func (c Client) AddStaticRoute(policy, cidr, nextHop, router string, routeType s
return nil
}

// AddPolicyRoute add a policy route rule in ovn
func (c Client) AddPolicyRoute(router string, priority int32, match string, action string, nextHop string) error {
// lr-policy-add ROUTER PRIORITY MATCH ACTION [NEXTHOP]
args := []string{MayExist, "lr-policy-add", strconv.Itoa(int(priority)), match, action}
if nextHop != "" {
args = append(args, nextHop)
}
if _, err := c.ovnNbCommand(args...); err != nil {
return err
}
return nil
}

// DeletePolicyRoute delete a policy route rule in ovn
func (c Client) DeletePolicyRoute(router string, priority int32, match string) error {
var args = []string{IfExists, "lr-policy-del", router}
// lr-policy-del ROUTER [PRIORITY [MATCH]]
if priority > 0 {
args = append(args, strconv.Itoa(int(priority)))
if match != "" {
args = append(args, match)
}
}
_, err := c.ovnNbCommand(args...)
return err
}

type PolicyRoute struct {
Priority int32
Match string
Action string
NextHopIP string
}

func (c Client) GetPolicyRouteList(router string) (routeList []*PolicyRoute, err error) {
output, err := c.ovnNbCommand("lr-policy-list", router)
if err != nil {
klog.Errorf("failed to list logical router policy route: %v", err)
return nil, err
}
return parseLrPolicyRouteListOutput(output)
}

var policyRouteRegexp = regexp.MustCompile(`^\s*(\d+)\s+(.*)\b\s+(allow|drop|reroute)\s*(.*)?$`)

func parseLrPolicyRouteListOutput(output string) (routeList []*PolicyRoute, err error) {
lines := strings.Split(output, "\n")
routeList = make([]*PolicyRoute, 0, len(lines))
for _, l := range lines {
if len(l) == 0 {
continue
}
sm := policyRouteRegexp.FindStringSubmatch(l)
if len(sm) != 5 {
continue
}
priority, err := strconv.ParseInt(sm[1], 10, 32)
if err != nil {
return nil, fmt.Errorf("found unexpeted policy priority %s, please check", sm[1])
}
routeList = append(routeList, &PolicyRoute{
Priority: int32(priority),
Match: sm[2],
Action: sm[3],
NextHopIP: sm[4],
})
}
return routeList, nil
}

func (c Client) GetStaticRouteList(router string) (routeList []*StaticRoute, err error) {
output, err := c.ovnNbCommand("lr-route-list", router)
if err != nil {
Expand Down
12 changes: 12 additions & 0 deletions pkg/ovs/ovn-nbctl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,15 @@ func Test_parseLrRouteListOutput(t *testing.T) {
ast.Nil(err)
ast.Equal(6, len(routeList))
}

func Test_parseLrPolicyRouteListOutput(t *testing.T) {
ast := assert.New(t)
output := `
10 ip4.src == 1.1.0.0/24 reroute 198.19.0.4
10 ip4.src == 1.1.0.0/24 || ip4.src == 1.1.4.0/24 reroute 198.19.0.4
10 ip4.src == 1.1.0.0/24 || ip4.src == 1.1.4.0/24 || Iip4.src ==1.1.5.0/24 reroute 198.19.0.4
10 ip4.src == 1.1.1.0/24 drop`
routeList, err := parseLrPolicyRouteListOutput(output)
ast.Nil(err)
ast.Equal(6, len(routeList))
}
13 changes: 13 additions & 0 deletions yamls/crd-pre-1.16.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,19 @@ spec:
type: string
type: object
type: array
policyRoutes:
items:
properties:
priority:
type: integer
action:
type: string
match:
type: string
nextHopIP:
type: string
type: object
type: array
type: object
status:
properties:
Expand Down
13 changes: 13 additions & 0 deletions yamls/crd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,19 @@ spec:
type: string
type: object
type: array
policyRoutes:
items:
properties:
priority:
type: integer
action:
type: string
match:
type: string
nextHopIP:
type: string
type: object
type: array
type: object
status:
properties:
Expand Down

0 comments on commit 871c149

Please sign in to comment.