Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IPAM sends GARPS to updating arp cache table #4688

Closed
wants to merge 1 commit into from
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
28 changes: 26 additions & 2 deletions cmd/spiderpool/cmd/command_add.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"github.com/spidernet-io/spiderpool/api/v1/agent/models"
"github.com/spidernet-io/spiderpool/pkg/constant"
spiderpoolip "github.com/spidernet-io/spiderpool/pkg/ip"
"github.com/spidernet-io/spiderpool/pkg/networking/networking"
"github.com/spidernet-io/spiderpool/pkg/openapi"
)

Expand Down Expand Up @@ -164,8 +165,7 @@
// do ip conflict and gateway detection
logger.Sugar().Info("postIpam response",
zap.Any("DNS", ipamResponse.Payload.DNS),
zap.Any("Routes", ipamResponse.Payload.Routes),
zap.Any("Ips", ipamResponse.Payload.Ips))
zap.Any("Routes", ipamResponse.Payload.Routes))

if err = DetectIPConflictAndGatewayReachable(logger, args.IfName, hostNs, netns, ipamResponse.Payload.Ips); err != nil {
if errors.Is(err, constant.ErrIPConflict) || errors.Is(err, constant.ErrGatewayUnreachable) {
Expand All @@ -179,6 +179,30 @@
return err
}

// CNI will set the interface to up, and the kernel only sends GARPs/Unsolicited NA when the interface
// goes from down to up or when the link-layer address changes on the interfaces. in order to the
// kernel send GARPs/Unsolicited NA when the interface goes from down to up.
// see https://github.com/spidernet-io/spiderpool/issues/4650
var ipRes []net.IP
for _, i := range ipamResponse.Payload.Ips {
if i.Address != nil && *i.Address != "" {
ipa, _, err := net.ParseCIDR(*i.Address)
if err != nil {
logger.Error(err.Error())
continue

Check warning on line 192 in cmd/spiderpool/cmd/command_add.go

View check run for this annotation

Codecov / codecov/patch

cmd/spiderpool/cmd/command_add.go#L191-L192

Added lines #L191 - L192 were not covered by tests
}
ipRes = append(ipRes, ipa)
}
}

err = netns.Do(func(netNS ns.NetNS) error {
return networking.AnnounceIPs(logger, args.IfName, ipRes)
})

if err != nil {
logger.Error(err.Error())
}

Check warning on line 204 in cmd/spiderpool/cmd/command_add.go

View check run for this annotation

Codecov / codecov/patch

cmd/spiderpool/cmd/command_add.go#L203-L204

Added lines #L203 - L204 were not covered by tests

// Assemble the result of IPAM request response.
result, err := assembleResult(conf.CNIVersion, args.IfName, ipamResponse)
if err != nil {
Expand Down
32 changes: 0 additions & 32 deletions pkg/multuscniconfig/multusconfig_validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,6 @@ func validateCNIConfig(multusConfig *spiderpoolv2beta1.SpiderMultusConfig) *fiel
}
}

if injectNetworkResource {
if err := ValidateNetworkResouce(multusConfig.Name, multusConfig.Namespace, multusConfig.Spec.MacvlanConfig.RdmaResourceName, multusConfig.Spec.MacvlanConfig.SpiderpoolConfigPools); err != nil {
return field.Invalid(macvlanConfigField, *multusConfig.Spec.MacvlanConfig, err.Error())
}
}

case constant.IPVlanCNI:
if multusConfig.Spec.IPVlanConfig == nil {
return field.Required(ipvlanConfigField, fmt.Sprintf("no %s specified", ipvlanConfigField.String()))
Expand All @@ -147,12 +141,6 @@ func validateCNIConfig(multusConfig *spiderpoolv2beta1.SpiderMultusConfig) *fiel
}
}

if injectNetworkResource {
if err := ValidateNetworkResouce(multusConfig.Name, multusConfig.Namespace, multusConfig.Spec.IPVlanConfig.RdmaResourceName, multusConfig.Spec.IPVlanConfig.SpiderpoolConfigPools); err != nil {
return field.Invalid(ipvlanConfigField, *multusConfig.Spec.IPVlanConfig, err.Error())
}
}

case constant.SriovCNI:
if multusConfig.Spec.SriovConfig == nil {
return field.Required(sriovConfigField, fmt.Sprintf("no %s specified", sriovConfigField.String()))
Expand Down Expand Up @@ -183,13 +171,6 @@ func validateCNIConfig(multusConfig *spiderpoolv2beta1.SpiderMultusConfig) *fiel
return field.Invalid(sriovConfigField, *multusConfig.Spec.SriovConfig, err.Error())
}
}

if injectNetworkResource {
if err := ValidateNetworkResouce(multusConfig.Name, multusConfig.Namespace, multusConfig.Spec.SriovConfig.ResourceName, multusConfig.Spec.SriovConfig.SpiderpoolConfigPools); err != nil {
return field.Invalid(sriovConfigField, *multusConfig.Spec.SriovConfig, err.Error())
}
}

case constant.IBSriovCNI:
if multusConfig.Spec.IbSriovConfig == nil {
return field.Required(ibsriovConfigField, fmt.Sprintf("no %s specified", ibsriovConfigField.String()))
Expand All @@ -208,13 +189,6 @@ func validateCNIConfig(multusConfig *spiderpoolv2beta1.SpiderMultusConfig) *fiel
return field.Invalid(ibsriovConfigField, *multusConfig.Spec.IbSriovConfig, err.Error())
}
}

if injectNetworkResource {
if err := ValidateNetworkResouce(multusConfig.Name, multusConfig.Namespace, multusConfig.Spec.IbSriovConfig.ResourceName, multusConfig.Spec.IbSriovConfig.SpiderpoolConfigPools); err != nil {
return field.Invalid(ibsriovConfigField, *multusConfig.Spec.IbSriovConfig, err.Error())
}
}

case constant.IPoIBCNI:
if multusConfig.Spec.IpoibConfig == nil {
return field.Required(ipoibConfigField, fmt.Sprintf("no %s specified", ipoibConfigField.String()))
Expand All @@ -234,12 +208,6 @@ func validateCNIConfig(multusConfig *spiderpoolv2beta1.SpiderMultusConfig) *fiel
}
}

if injectNetworkResource {
if err := ValidateNetworkResouce(multusConfig.Name, multusConfig.Namespace, multusConfig.Spec.IpoibConfig.Master, multusConfig.Spec.IpoibConfig.SpiderpoolConfigPools); err != nil {
return field.Invalid(ipoibConfigField, *multusConfig.Spec.IpoibConfig, err.Error())
}
}

case constant.OvsCNI:
if injectRdmaResource || injectNetworkResource {
return field.Forbidden(cniTypeField, fmt.Sprintf("the cniType %s does not support RDMA resource or network resource injected", *multusConfig.Spec.CniType))
Expand Down
37 changes: 37 additions & 0 deletions pkg/networking/networking/packet.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"syscall"
"time"

"go.uber.org/zap"
"golang.org/x/net/icmp"
"golang.org/x/net/ipv6"
"golang.org/x/sys/unix"
Expand Down Expand Up @@ -313,3 +314,39 @@ func ParseIPv6NeighborAdvertisementMsg(n int, buf []byte) (srcIP net.IP, mac net
}
return
}

func AnnounceIPs(logger *zap.Logger, iface string, ips []net.IP) error {
l, err := netlink.LinkByName(iface)
if err != nil {
return err
}

for _, addr := range ips {
logger.Debug("announcing ip", zap.String("ip", addr.String()), zap.String("interface", iface))
if addr.To4() != nil {
// send an gratuitous arp to announce the new mac address
if err = SendARPReuqest(l, addr, addr); err != nil {
logger.Error("failed to send gratuitous arps", zap.Error(err))
} else {
logger.Info("Send gratuitous arps successfully", zap.String("interface", iface))
}
} else {
ifi, err := net.InterfaceByName(iface)
if err != nil {
return fmt.Errorf("failed to InterfaceByName %s: %w", iface, err)
}

ndpClient, _, err := ndp.Listen(ifi, ndp.LinkLocal)
if err != nil {
return fmt.Errorf("failed to init ndp client: %w", err)
}
defer ndpClient.Close()
if err = SendUnsolicitedNeighborAdvertisement(addr, ifi, ndpClient); err != nil {
logger.Error("failed to send unsolicited neighbor advertisements", zap.Error(err))
} else {
logger.Info("Send unsolicited neighbor advertisements successfully", zap.String("interface", iface))
}
}
}
return nil
}
24 changes: 11 additions & 13 deletions test/e2e/spidermultus/spidermultus_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -805,26 +805,25 @@ var _ = Describe("test spidermultus", Label("SpiderMultusConfig"), func() {

It("resoucename and ippools config must be both set when spidermutlus with annotation: cni.spidernet.io/network-resource-inject", Label("M00031"), func() {
var smcName string = "ann-network-resource" + common.GenerateString(10, true)
smc := &spiderpoolv2beta1.SpiderMultusConfig{
smc := &v2beta1.SpiderMultusConfig{
ObjectMeta: metav1.ObjectMeta{
Name: smcName,
Namespace: namespace,
Annotations: map[string]string{
constant.AnnoNetworkResourceInject: "test",
},
},
Spec: spiderpoolv2beta1.MultusCNIConfigSpec{
Spec: v2beta1.MultusCNIConfigSpec{
CniType: ptr.To(constant.MacvlanCNI),
MacvlanConfig: &spiderpoolv2beta1.SpiderMacvlanCniConfig{
MacvlanConfig: &v2beta1.SpiderMacvlanCniConfig{
Master: []string{common.NIC1},
EnableRdma: true,
RdmaResourceName: "test",
SpiderpoolConfigPools: &spiderpoolv2beta1.SpiderpoolPools{
RdmaResourceName: ptr.To("test"),
SpiderpoolConfigPools: &v2beta1.SpiderpoolPools{
IPv4IPPool: []string{"test"},
},
},
EnableCoordinator: ptr.To(true),
CoordinatorConfig: &spiderpoolv2beta1.CoordinatorSpec{
CoordinatorConfig: &v2beta1.CoordinatorSpec{
PodRPFilter: nil,
},
},
Expand All @@ -836,23 +835,22 @@ var _ = Describe("test spidermultus", Label("SpiderMultusConfig"), func() {

It("return an err if resoucename is set without ippools config when spidermutlus with annotation: cni.spidernet.io/network-resource-inject", Label("M00032"), func() {
var smcName string = "ann-network-resource" + common.GenerateString(10, true)
smc := &spiderpoolv2beta1.SpiderMultusConfig{
smc := &v2beta1.SpiderMultusConfig{
ObjectMeta: metav1.ObjectMeta{
Name: smcName,
Namespace: namespace,
Annotations: map[string]string{
constant.AnnoNetworkResourceInject: "test",
},
},
Spec: spiderpoolv2beta1.MultusCNIConfigSpec{
Spec: v2beta1.MultusCNIConfigSpec{
CniType: ptr.To(constant.MacvlanCNI),
MacvlanConfig: &spiderpoolv2beta1.SpiderMacvlanCniConfig{
MacvlanConfig: &v2beta1.SpiderMacvlanCniConfig{
Master: []string{common.NIC1},
EnableRdma: true,
RdmaResourceName: "test",
RdmaResourceName: ptr.To("test"),
},
EnableCoordinator: ptr.To(true),
CoordinatorConfig: &spiderpoolv2beta1.CoordinatorSpec{
CoordinatorConfig: &v2beta1.CoordinatorSpec{
PodRPFilter: nil,
},
},
Expand Down
Loading