Skip to content
Merged
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
11 changes: 9 additions & 2 deletions calico-vpp-agent/cni/cni_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -400,10 +400,17 @@ func (s *Server) createRedirectToHostRules() (uint32, error) {
return types.InvalidID, fmt.Errorf("no main interface found")
}
for _, rule := range config.GetCalicoVppInitialConfig().RedirectToHostRules {
mainInterfaceAddress := mainInterface.GetAddress(vpplink.IPFamilyFromIP(rule.IP))
if mainInterfaceAddress == nil {
return types.InvalidID, fmt.Errorf("error installing rule %v no address found on uplink", rule)
}
err = s.vpp.AddSessionRedirect(&types.SessionRedirect{
FiveTuple: types.NewDst3Tuple(rule.Proto, net.ParseIP(rule.IP), rule.Port),
FiveTuple: types.NewDst3Tuple(rule.Proto, rule.IP, rule.Port),
TableIndex: index,
}, &types.RoutePath{Gw: config.VppHostPuntFakeGatewayAddress, SwIfIndex: mainInterface.TapSwIfIndex})
}, &types.RoutePath{
Gw: mainInterfaceAddress.IP,
SwIfIndex: mainInterface.TapSwIfIndex,
})
if err != nil {
return types.InvalidID, err
}
Expand Down
27 changes: 22 additions & 5 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,11 +149,17 @@ var (
/* Bash script template run when VPP stops with an error */
HookScriptVppErrored = StringEnvVar("CALICOVPP_HOOK_VPP_ERRORED", "")

Info = &VppManagerInfo{}
Info = &VppManagerInfo{
UplinkStatuses: make(map[string]UplinkStatus),
PhysicalNets: make(map[string]PhysicalNetwork),
}

// VppHostPuntFakeGatewayAddress is the fake gateway we use with a static neighbor
// in the punt table to route punted packets to the host
VppHostPuntFakeGatewayAddress = net.ParseIP("169.254.0.1")
// VppsideTap0Address is the IP address we add to the tap0
// so that it can receive ipv4 packets
VppsideTap0Address = PrefixEnvVar(
"CALICOVPP_TAP0_ADDR",
MustParseCIDR("169.254.0.1/32"),
)
)

/* RunHook() executes a bash script at a specific hook point.
Expand Down Expand Up @@ -289,7 +295,7 @@ func (u *UplinkInterfaceSpec) String() string {

type RedirectToHostRulesConfigType struct {
Port uint16 `json:"port,omitempty"`
IP string `json:"ip,omitempty"`
IP net.IP `json:"ip,omitempty"`
/* "tcp", "udp",... */
Proto types.IPProto `json:"proto,omitempty"`
}
Expand Down Expand Up @@ -587,6 +593,17 @@ type UplinkStatus struct {
// FakeNextHopIP6 is the computed next hop for v6 routes added
// in linux to (ServiceCIDR, podCIDR, etc...) towards this interface
FakeNextHopIP6 net.IP

UplinkAddresses []*net.IPNet
}

func (uplinkStatus *UplinkStatus) GetAddress(ipFamily vpplink.IPFamily) *net.IPNet {
for _, addr := range uplinkStatus.UplinkAddresses {
if vpplink.IPFamilyFromIPNet(addr) == ipFamily {
return addr
}
}
return nil
}

type PhysicalNetwork struct {
Expand Down
13 changes: 12 additions & 1 deletion config/config_parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,18 @@ func prefixParser(value string) (net.IPNet, error) {
func RequiredPrefixEnvVar(varName string) *net.IPNet {
return RequiredEnvVar(varName, net.IPNet{}, prefixParser)
}
func PrefixEnvVar(varName string) *net.IPNet { return EnvVar(varName, net.IPNet{}, prefixParser) }

func PrefixEnvVar(varName string, defaultValue *net.IPNet) *net.IPNet {
return EnvVar(varName, *defaultValue, prefixParser)
}

func MustParseCIDR(str string) *net.IPNet {
_, cidr, err := net.ParseCIDR(str)
if err != nil {
logrus.Fatalf("error parsing %s as cidr %v", str, err)
}
return cidr
}

func prefixListParser(value string) ([]*net.IPNet, error) {
chunks := strings.Split(value, ",")
Expand Down
94 changes: 52 additions & 42 deletions vpp-manager/vpp_runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,30 +142,20 @@ func (v *VppRunner) configureGlobalPunt() (err error) {
}

func (v *VppRunner) configurePunt(tapSwIfIndex uint32, ifState config.LinuxInterfaceState) (err error) {
err = v.vpp.AddNeighbor(&types.Neighbor{
SwIfIndex: tapSwIfIndex,
IP: config.VppHostPuntFakeGatewayAddress,
HardwareAddr: ifState.HardwareAddr,
Flags: types.IPNeighborStatic,
})
if err != nil {
return errors.Wrapf(err, "Error adding neighbor %s to tap", config.VppHostPuntFakeGatewayAddress)
}
/* In the punt table (where all punted traffics ends), route to the tap */
for _, address := range ifState.Addresses {
for _, addr := range ifState.Addresses {
err = v.vpp.RouteAdd(&types.Route{
Dst: address.IPNet,
Table: common.PuntTableID,
Dst: addr.IPNet,
Paths: []types.RoutePath{{
Gw: config.VppHostPuntFakeGatewayAddress,
Gw: addr.IP,
SwIfIndex: tapSwIfIndex,
}},
})
if err != nil {
return errors.Wrapf(err, "error adding vpp side routes for interface")
}
}

return nil
}

Expand Down Expand Up @@ -446,26 +436,42 @@ func (v *VppRunner) setupTapVRF(ifSpec *config.UplinkInterfaceSpec, ifState *con
return []uint32{}, errors.Wrapf(err, "error setting vpp tap in vrf %d", vrfID)
}
vrfs = append(vrfs, vrfID)
}

// Configure addresses to enable ipv4 & ipv6 on the tap
for _, addr := range ifState.Addresses {
if addr.IP.IsLinkLocalUnicast() && !common.IsFullyQualified(addr.IPNet) && common.IsV6Cidr(addr.IPNet) {
log.Infof("Not adding address %s to data interface (vpp requires /128 link-local)", addr.String())
continue
} else {
log.Infof("Adding address %s to tap interface", addr.String())
}
// to max len cidr because we don't want the rest of the subnet to be considered as
// connected to that interface
// note that the role of these addresses is just to tell vpp to accept ip4 / ip6 packets on the tap
// we use these addresses as the safest option, because as they are configured on linux, linux
// will never send us packets with these addresses as destination
err = v.vpp.AddInterfaceAddress(tapSwIfIndex, common.ToMaxLenCIDR(addr.IP))
if err != nil {
log.Errorf("Error adding address to tap interface: %v", err)
for _, addr := range ifState.Addresses {
if vpplink.IPFamilyFromIP(addr.IP) == ipFamily {
err = v.vpp.RouteAdd(&types.Route{
Table: vrfID,
Dst: common.FullyQualified(addr.IP),
Paths: []types.RoutePath{{
Gw: addr.IP,
SwIfIndex: tapSwIfIndex,
}},
})
if err != nil {
return []uint32{}, errors.Wrapf(err, "error add route from VPP to tap0 in VRF %d", vrfID)
}
err = v.vpp.AddNeighbor(&types.Neighbor{
SwIfIndex: tapSwIfIndex,
IP: addr.IP,
HardwareAddr: ifState.HardwareAddr,
Flags: types.IPNeighborStatic,
})
if err != nil {
return []uint32{}, errors.Wrapf(err, "error add static neighbor for tap0 in VRF %d", vrfID)
}
}
}
}

err = v.vpp.EnableInterfaceIP6(tapSwIfIndex)
if err != nil {
return []uint32{}, errors.Wrapf(err, "error enabling ip6 for tap %d", tapSwIfIndex)
}

err = v.vpp.AddInterfaceAddress(tapSwIfIndex, config.VppsideTap0Address)
if err != nil {
return []uint32{}, errors.Wrapf(err, "error adding vpp side address for tap0 %d", tapSwIfIndex)
}
return vrfs, nil
}

Expand Down Expand Up @@ -691,18 +697,22 @@ func (v *VppRunner) configureVppUplinkInterface(
return errors.Wrap(err, "Error setting tap up")
}

if config.Info.UplinkStatuses != nil {
config.Info.UplinkStatuses[link.Attrs().Name] = config.UplinkStatus{
TapSwIfIndex: tapSwIfIndex,
SwIfIndex: ifSpec.SwIfIndex,
Mtu: uplinkMtu,
PhysicalNetworkName: ifSpec.PhysicalNetworkName,
LinkIndex: link.Attrs().Index,
Name: link.Attrs().Name,
IsMain: ifSpec.IsMain,
FakeNextHopIP4: fakeNextHopIP4,
FakeNextHopIP6: fakeNextHopIP6,
}
uplinkAddresses := make([]*net.IPNet, 0)
for _, addr := range ifState.Addresses {
uplinkAddresses = append(uplinkAddresses, addr.IPNet)
}

config.Info.UplinkStatuses[link.Attrs().Name] = config.UplinkStatus{
TapSwIfIndex: tapSwIfIndex,
SwIfIndex: ifSpec.SwIfIndex,
Mtu: uplinkMtu,
PhysicalNetworkName: ifSpec.PhysicalNetworkName,
LinkIndex: link.Attrs().Index,
Name: link.Attrs().Name,
IsMain: ifSpec.IsMain,
FakeNextHopIP4: fakeNextHopIP4,
FakeNextHopIP6: fakeNextHopIP6,
UplinkAddresses: uplinkAddresses,
}
return nil
}
Expand Down
Loading