Skip to content

Commit

Permalink
optimize lrp create for subnet in vpc (#1712)
Browse files Browse the repository at this point in the history
  • Loading branch information
hongzhen-ma committed Jul 22, 2022
1 parent 994885c commit 7841f08
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 30 deletions.
11 changes: 9 additions & 2 deletions pkg/controller/subnet.go
Expand Up @@ -487,15 +487,15 @@ func (c *Controller) handleAddOrUpdateSubnet(key string) error {
return err
}

cachedSubnet, err = c.subnetsLister.Get(key)
subnet, err = c.config.KubeOvnClient.KubeovnV1().Subnets().Get(context.Background(), key, metav1.GetOptions{})
if err != nil {
if k8serrors.IsNotFound(err) {
return nil
}
klog.Errorf("failed to get subnet %s error %v", key, err)
return err
}

subnet = cachedSubnet.DeepCopy()
deleted, err := c.handleSubnetFinalizer(subnet)
if err != nil {
klog.Errorf("handle subnet finalizer failed %v", err)
Expand Down Expand Up @@ -625,6 +625,13 @@ func (c *Controller) handleAddOrUpdateSubnet(key string) error {
c.patchSubnetStatus(subnet, "CreateLogicalSwitchFailed", err.Error())
return err
}

if needRouter {
if err := c.reconcileRouterPortBySubnet(vpc, subnet); err != nil {
klog.Errorf("failed to connect switch %s to router %s, %v", subnet.Name, vpc.Name, err)
return err
}
}
} else {
// logical switch exists, only update other_config
if err := c.ovnLegacyClient.SetLogicalSwitchConfig(subnet.Name, vpc.Status.Router, subnet.Spec.Protocol, subnet.Spec.CIDRBlock, subnet.Spec.Gateway, subnet.Spec.ExcludeIps, needRouter); err != nil {
Expand Down
43 changes: 34 additions & 9 deletions pkg/controller/vpc.go
Expand Up @@ -199,6 +199,35 @@ func (c *Controller) reconcileRouterPorts(vpc *kubeovnv1.Vpc) error {
return nil
}

func (c *Controller) reconcileRouterPortBySubnet(vpc *kubeovnv1.Vpc, subnet *kubeovnv1.Subnet) error {
router := vpc.Name
routerPortName := ovs.LogicalRouterPortName(router, subnet.Name)
exists, err := c.ovnClient.LogicalRouterPortExists(routerPortName)
if err != nil {
return err
}

if !exists {
subnet, err := c.subnetsLister.Get(subnet.Name)
if err != nil {
if k8serrors.IsNotFound(err) {
return nil
}
klog.Errorf("failed to get subnet %s, err %v", subnet.Name, err)
return err
}

networks := util.GetIpAddrWithMask(subnet.Spec.Gateway, subnet.Spec.CIDRBlock)
klog.Infof("router port does not exist, trying to create %s with ip %s", routerPortName, networks)

if err := c.ovnClient.AddLogicalRouterPort(router, routerPortName, "", networks); err != nil {
klog.Errorf("failed to create router port %s, err %v", routerPortName, err)
return err
}
}
return nil
}

type VpcLoadBalancer struct {
TcpLoadBalancer string
TcpSessLoadBalancer string
Expand Down Expand Up @@ -660,17 +689,13 @@ func (c *Controller) getVpcSubnets(vpc *kubeovnv1.Vpc) (subnets []string, defaul
}

for _, subnet := range allSubnets {
deleted, err := c.handleSubnetFinalizer(subnet)
if err != nil {
klog.Errorf("handle subnet finalizer failed %v", err)
return nil, "", err
if subnet.Spec.Vpc != vpc.Name || !subnet.DeletionTimestamp.IsZero() {
continue
}

if !deleted && subnet.Spec.Vpc == vpc.Name {
subnets = append(subnets, subnet.Name)
if subnet.Spec.Default {
defaultSubnet = subnet.Name
}
subnets = append(subnets, subnet.Name)
if subnet.Spec.Default {
defaultSubnet = subnet.Name
}
}
return
Expand Down
27 changes: 27 additions & 0 deletions pkg/ovs/ovn-nb-logical_switch.go
@@ -0,0 +1,27 @@
package ovs

import (
"context"
"fmt"

"github.com/ovn-org/libovsdb/client"

"github.com/kubeovn/kube-ovn/pkg/ovsdb/ovnnb"
)

func (c OvnClient) GetLogicalSwitch(name string, ignoreNotFound bool) (*ovnnb.LogicalSwitch, error) {
ls := &ovnnb.LogicalSwitch{Name: name}
if err := c.ovnNbClient.Get(context.TODO(), ls); err != nil {
if ignoreNotFound && err == client.ErrNotFound {
return nil, nil
}
return nil, fmt.Errorf("failed to get logical switch %s: %v", name, err)
}

return ls, nil
}

func (c OvnClient) LogicalSwitchExists(name string) (bool, error) {
ls, err := c.GetLogicalSwitch(name, true)
return ls != nil, err
}
55 changes: 55 additions & 0 deletions pkg/ovs/ovn-nb-logical_switch_port.go
Expand Up @@ -5,8 +5,12 @@ import (
"fmt"

"github.com/ovn-org/libovsdb/client"
"github.com/ovn-org/libovsdb/model"
"github.com/ovn-org/libovsdb/ovsdb"

"k8s.io/klog/v2"

ovsclient "github.com/kubeovn/kube-ovn/pkg/ovsdb/client"
"github.com/kubeovn/kube-ovn/pkg/ovsdb/ovnnb"
"github.com/kubeovn/kube-ovn/pkg/util"
)
Expand Down Expand Up @@ -66,3 +70,54 @@ func (c OvnClient) LogicalSwitchPortExists(name string) (bool, error) {
lsp, err := c.GetLogicalSwitchPort(name, true)
return lsp != nil, err
}

func (c OvnClient) AddSwitchRouterPort(ls, lr string) error {
klog.Infof("add %s to %s", ls, lr)
lsTolr := fmt.Sprintf("%s-%s", ls, lr)
lrTols := fmt.Sprintf("%s-%s", lr, ls)

logicalSwitch, err := c.GetLogicalSwitch(ls, false)
if err != nil {
return err
}

var ops []ovsdb.Operation

lsp := &ovnnb.LogicalSwitchPort{
UUID: ovsclient.NamedUUID(),
Name: lsTolr,
Type: "router",
Addresses: []string{"router"},
Options: map[string]string{"router-port": lrTols},
ExternalIDs: map[string]string{"vendor": util.CniTypeName},
}

// ensure there is no port in the same name, before we create it in the transaction
waitOp := ConstructWaitForNameNotExistsOperation(lsTolr, "Logical_Switch_Port")
ops = append(ops, waitOp)

createOps, err := c.ovnNbClient.Create(lsp)
if err != nil {
return err
}
ops = append(ops, createOps...)

mutationOps, err := c.ovnNbClient.
Where(logicalSwitch).
Mutate(logicalSwitch,
model.Mutation{
Field: &logicalSwitch.Ports,
Mutator: ovsdb.MutateOperationInsert,
Value: []string{lsp.UUID},
},
)
if err != nil {
return err
}
ops = append(ops, mutationOps...)

if err := Transact(c.ovnNbClient, "lsp-add", ops, c.ovnNbClient.Timeout); err != nil {
return fmt.Errorf("failed to create logical switch port %s: %v", lsTolr, err)
}
return nil
}
22 changes: 3 additions & 19 deletions pkg/ovs/ovn-nbctl-legacy.go
Expand Up @@ -441,9 +441,7 @@ func (c LegacyClient) CreateLogicalSwitch(ls, lr, subnet, gateway string, needRo
}

if needRouter {
ip := util.GetIpAddrWithMask(gateway, subnet)
mac := util.GenerateMac()
if err := c.createRouterPort(ls, lr, ip, mac); err != nil {
if err := c.createRouterPort(ls, lr); err != nil {
klog.Errorf("failed to connect switch %s to router, %v", ls, err)
return err
}
Expand Down Expand Up @@ -776,8 +774,8 @@ func (c LegacyClient) RemoveRouterPort(ls, lr string) error {
return nil
}

func (c LegacyClient) createRouterPort(ls, lr, ip, mac string) error {
klog.Infof("add %s to %s with ip=%s, mac=%s", ls, lr, ip, mac)
func (c LegacyClient) createRouterPort(ls, lr string) error {
klog.Infof("add %s to %s", ls, lr)
lsTolr := fmt.Sprintf("%s-%s", ls, lr)
lrTols := fmt.Sprintf("%s-%s", lr, ls)
_, err := c.ovnNbCommand(MayExist, "lsp-add", ls, lsTolr, "--",
Expand All @@ -789,20 +787,6 @@ func (c LegacyClient) createRouterPort(ls, lr, ip, mac string) error {
klog.Errorf("failed to create switch router port %s: %v", lsTolr, err)
return err
}
if len(ip) == 0 {
klog.Errorf("failed to create switch router port: ip is empty")
return err
}
ipStr := strings.Split(ip, ",")
if len(ipStr) == 2 {
_, err = c.ovnNbCommand(MayExist, "lrp-add", lr, lrTols, mac, ipStr[0], ipStr[1])
} else {
_, err = c.ovnNbCommand(MayExist, "lrp-add", lr, lrTols, mac, ipStr[0])
}
if err != nil {
klog.Errorf("failed to create router port %s: %v", lrTols, err)
return err
}
return nil
}

Expand Down

0 comments on commit 7841f08

Please sign in to comment.