Skip to content

Commit

Permalink
vpcagent: ovn: manage static routes
Browse files Browse the repository at this point in the history
  • Loading branch information
yousong committed Apr 24, 2020
1 parent 0578d6c commit 05c38c8
Show file tree
Hide file tree
Showing 6 changed files with 147 additions and 30 deletions.
98 changes: 76 additions & 22 deletions pkg/vpcagent/ovn/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ package ovn

import (
"context"
"crypto/md5"
"fmt"
"strings"

"yunion.io/x/pkg/errors"

apis "yunion.io/x/onecloud/pkg/apis/compute"
agentmodels "yunion.io/x/onecloud/pkg/vpcagent/models"
"yunion.io/x/onecloud/pkg/vpcagent/ovn/mac"
"yunion.io/x/onecloud/pkg/vpcagent/ovnutil"
)

Expand All @@ -44,6 +44,7 @@ func DumpOVNNorthbound(ctx context.Context, cli *ovnutil.OvnNbCtl) (*OVNNorthbou
&db.LogicalSwitchPort,
&db.LogicalRouter,
&db.LogicalRouterPort,
&db.LogicalRouterStaticRoute,
&db.DHCPOptions,
}
args := []string{"--format=json", "list", "<tbl>"}
Expand Down Expand Up @@ -84,7 +85,7 @@ func (keeper *OVNNorthboundKeeper) ClaimVpc(ctx context.Context, vpc *agentmodel
}
vpcRhp := &ovnutil.LogicalRouterPort{
Name: vpcRhpName(vpc.Id),
Mac: hashMac(vpc.Id, "rp"),
Mac: apis.VpcMappedGatewayMac,
Networks: []string{fmt.Sprintf("%s/%d", apis.VpcMappedGatewayIP(), apis.VpcMappedIPMask)},
}
vpcHrp := &ovnutil.LogicalSwitchPort{
Expand Down Expand Up @@ -113,27 +114,11 @@ func (keeper *OVNNorthboundKeeper) ClaimVpc(ctx context.Context, vpc *agentmodel
return keeper.cli.Must(ctx, "ClaimVpc", args)
}

func hashMac(in ...string) string {
h := md5.New()
for _, s := range in {
h.Write([]byte(s))
}
sum := h.Sum(nil)
b := sum[0]
b &= 0xfe
b |= 0x02
mac := fmt.Sprintf("%02x", b)
for _, b := range sum[1:6] {
mac += fmt.Sprintf(":%02x", b)
}
return mac
}

func (keeper *OVNNorthboundKeeper) ClaimNetwork(ctx context.Context, network *agentmodels.Network) error {
var (
rpMac = hashMac(network.Id, "rp")
dhcpMac = hashMac(network.Id, "dhcp")
mdMac = hashMac(network.Id, "md")
rpMac = mac.HashMac(network.Id, "rp")
dhcpMac = mac.HashMac(network.Id, "dhcp")
mdMac = mac.HashMac(network.Id, "md")
mdIp = "169.254.169.254"
)
netLs := &ovnutil.LogicalSwitch{
Expand Down Expand Up @@ -195,9 +180,43 @@ func (keeper *OVNNorthboundKeeper) ClaimNetwork(ctx context.Context, network *ag
return keeper.cli.Must(ctx, "ClaimNetwork", args)
}

func (keeper *OVNNorthboundKeeper) ClaimVpcHost(ctx context.Context, vpc *agentmodels.Vpc, host *agentmodels.Host) error {
var (
ocVersion = fmt.Sprintf("%s.%d", host.UpdatedAt, host.UpdateVersion)
)
vpcHostLsp := &ovnutil.LogicalSwitchPort{
Name: vpcHostLspName(vpc.Id, host.Id),
Addresses: []string{fmt.Sprintf("%s %s", mac.HashMac(host.Id), host.OvnMappedIpAddr)},
}
if m := keeper.DB.LogicalSwitchPort.FindOneMatchNonZeros(vpcHostLsp); m != nil {
m.OvnSetExternalIds(externalKeyOcVersion, ocVersion)
return nil
} else {
args := []string{
"--bare", "--columns=_uuid", "find", vpcHostLsp.OvnTableName(),
fmt.Sprintf("name=%q", vpcHostLsp.Name),
}
res := keeper.cli.Must(ctx, "find vpcHostLsp", args)
vpcHostLspUuid := strings.TrimSpace(res.Output)
if vpcHostLspUuid != "" {
return nil
}
}
var args []string
args = append(args, ovnCreateArgs(vpcHostLsp, vpcHostLsp.Name)...)
args = append(args, "--", "add", "Logical_Switch", vpcHostLsName(vpc.Id), "ports", "@"+vpcHostLsp.Name)
return keeper.cli.Must(ctx, "ClaimVpcHost", args)
}

func (keeper *OVNNorthboundKeeper) ClaimGuestnetwork(ctx context.Context, guestnetwork *agentmodels.Guestnetwork) error {
var (
guest = guestnetwork.Guest
network = guestnetwork.Network
vpc = network.Vpc
host = guest.Host

ocVersion = fmt.Sprintf("%s.%d", guestnetwork.UpdatedAt, guestnetwork.UpdateVersion)
ocGnrRef = fmt.Sprintf("gnr/%s/%s/%s", vpc.Id, guestnetwork.GuestId, guestnetwork.Ifname)
dhcpOpt string
)

Expand Down Expand Up @@ -228,14 +247,28 @@ func (keeper *OVNNorthboundKeeper) ClaimGuestnetwork(ctx context.Context, guestn
PortSecurity: []string{fmt.Sprintf("%s %s/%d", guestnetwork.MacAddr, guestnetwork.IpAddr, guestnetwork.Network.GuestIpMask)},
Dhcpv4Options: &dhcpOpt,
}

gnrPolicy := "src-ip"
gnr := &ovnutil.LogicalRouterStaticRoute{
Policy: &gnrPolicy,
IpPrefix: guestnetwork.IpAddr + "/32",
Nexthop: host.OvnMappedIpAddr,
ExternalIds: map[string]string{
externalKeyOcRef: ocGnrRef,
},
}

allFound, args := cmp(&keeper.DB, ocVersion,
gnp,
gnr,
)
if allFound {
return nil
}
args = append(args, ovnCreateArgs(gnp, gnp.Name)...)
args = append(args, ovnCreateArgs(gnr, "gnr")...)
args = append(args, "--", "add", "Logical_Switch", netLsName(guestnetwork.NetworkId), "ports", "@"+gnp.Name)
args = append(args, "--", "add", "Logical_Router", vpcLrName(vpc.Id), "static_routes", "@gnr")
return keeper.cli.Must(ctx, "ClaimGuestnetwork", args)
}

Expand All @@ -246,6 +279,7 @@ func (keeper *OVNNorthboundKeeper) Mark(ctx context.Context) {
&db.LogicalSwitchPort,
&db.LogicalRouter,
&db.LogicalRouterPort,
&db.LogicalRouterStaticRoute,
&db.DHCPOptions,
}
for _, itbl := range itbls {
Expand Down Expand Up @@ -276,7 +310,27 @@ func (keeper *OVNNorthboundKeeper) Sweep(ctx context.Context) error {
}
args := ovnutil.OvnNbctlArgsDestroy(irows)
if len(args) > 0 {
return keeper.cli.Must(ctx, "Sweep", args)
keeper.cli.Must(ctx, "Sweep", args)
}

{
var args []string
for _, irow := range db.LogicalRouterStaticRoute.Rows() {
_, ok := irow.OvnGetExternalIds(externalKeyOcVersion)
if !ok {
ref, ok := irow.OvnGetExternalIds(externalKeyOcRef)
if ok {
parts := strings.SplitN(ref, "/", 4)
if len(parts) == 4 {
vpcId := parts[1]
args = append(args, "--", "remove", "Logical_Router", vpcLrName(vpcId), "static_routes", irow.OvnUuid())
}
}
}
}
if len(args) > 0 {
keeper.cli.Must(ctx, "Sweep static routes", args)
}
}
return nil
}
1 change: 1 addition & 0 deletions pkg/vpcagent/ovn/mac/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package mac // import "yunion.io/x/onecloud/pkg/vpcagent/ovn/mac"
22 changes: 22 additions & 0 deletions pkg/vpcagent/ovn/mac/mac.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package mac

import (
"crypto/md5"
"fmt"
)

func HashMac(in ...string) string {
h := md5.New()
for _, s := range in {
h.Write([]byte(s))
}
sum := h.Sum(nil)
b := sum[0]
b &= 0xfe
b |= 0x02
mac := fmt.Sprintf("%02x", b)
for _, b := range sum[1:6] {
mac += fmt.Sprintf(":%02x", b)
}
return mac
}
23 changes: 15 additions & 8 deletions pkg/vpcagent/ovn/names.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,37 +5,44 @@ import (
)

func vpcLrName(vpcId string) string {
return fmt.Sprintf("vpc-r-%s", vpcId)
return fmt.Sprintf("vpc-r/%s", vpcId)
}

func vpcHostLsName(vpcId string) string {
return fmt.Sprintf("vpc-h-%s", vpcId)
return fmt.Sprintf("vpc-h/%s", vpcId)
}

func vpcRhpName(vpcId string) string {
return fmt.Sprintf("vpc-rh-%s", vpcId)
return fmt.Sprintf("vpc-rh/%s", vpcId)
}

func vpcHrpName(vpcId string) string {
return fmt.Sprintf("vpc-hr-%s", vpcId)
return fmt.Sprintf("vpc-hr/%s", vpcId)
}

func vpcHostLspName(vpcId string, hostId string) string {
return fmt.Sprintf("vpc-h/%s/%s", vpcId, hostId)
}

func netLsName(netId string) string {
return fmt.Sprintf("subnet-%s", netId)
return fmt.Sprintf("subnet/%s", netId)
}

func netNrpName(netId string) string {
return fmt.Sprintf("subnet-nr-%s", netId)
return fmt.Sprintf("subnet-nr/%s", netId)
}

func netRnpName(netId string) string {
return fmt.Sprintf("subnet-rn-%s", netId)
return fmt.Sprintf("subnet-rn/%s", netId)
}

func netMdpName(netId string) string {
return fmt.Sprintf("subnet-md-%s", netId)
return fmt.Sprintf("subnet-md/%s", netId)
}

// gnpName returns Logical_Switch_Port name for guestnetwork
//
// The name must match what's going to be set on each chassis
func gnpName(netId string, ifname string) string {
return fmt.Sprintf("iface-%s-%s", netId, ifname)
}
31 changes: 31 additions & 0 deletions pkg/vpcagent/ovn/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import (
"yunion.io/x/log"
"yunion.io/x/pkg/errors"

"yunion.io/x/onecloud/pkg/mcclient/auth"
mcclient_modules "yunion.io/x/onecloud/pkg/mcclient/modules"
"yunion.io/x/onecloud/pkg/vpcagent/apihelper"
agentmodels "yunion.io/x/onecloud/pkg/vpcagent/models"
"yunion.io/x/onecloud/pkg/vpcagent/options"
Expand Down Expand Up @@ -112,6 +114,35 @@ func (w *Worker) run(ctx context.Context, mss *agentmodels.ModelSets) (err error
for _, network := range vpc.Networks {
ovndb.ClaimNetwork(ctx, network)
for _, guestnetwork := range network.Guestnetworks {
var (
guest = guestnetwork.Guest
network = guestnetwork.Network
vpc = network.Vpc
host = guest.Host
)
if host.OvnVersion == "" {
// Just in case. This should never happen
log.Errorf("host %s(%s) of vpc guestnetwork (%s,%s) has no ovn support",
host.Id, host.Name, guestnetwork.NetworkId, guestnetwork.IpAddr)
continue
}
if host.OvnMappedIpAddr == "" {
// trigger ovn mapped ip addr allocation
apiVersion := "v2"
s := auth.GetAdminSession(ctx, w.opts.Region, apiVersion)
j, err := mcclient_modules.Hosts.Update(s, host.Id, nil)
if err != nil {
log.Errorf("host %s(%s) dummy update err: %v", host.Id, host.Name, err)
continue
}
j.Unmarshal(host) // update local copy in place
if host.OvnMappedIpAddr == "" {
log.Errorf("host %s(%s) has no mapped addr", host.Id, host.Name)
continue
}
}

ovndb.ClaimVpcHost(ctx, vpc, host)
ovndb.ClaimGuestnetwork(ctx, guestnetwork)
}
}
Expand Down
2 changes: 2 additions & 0 deletions pkg/vpcagent/ovnutil/ovn_nbctl.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,8 @@ func OvnNbctlArgsDestroy(irows []IRow) []string {
args = append(args, "--", "--if-exists", "lsp-del", irow.OvnUuid())
case *LogicalRouterPort:
args = append(args, "--", "--if-exists", "lrp-del", irow.OvnUuid())
case *LogicalRouterStaticRoute:
// find out vpc id/logical router from external_ids
default:
if !irow.OvnIsRoot() {
panic(irow.OvnTableName())
Expand Down

0 comments on commit 05c38c8

Please sign in to comment.