agent/eni/watcher/watcher_linux.go
func (udevWatcher *UdevWatcher) sendENIStateChangeWithRetries(parentCtx context.Context,
	macAddress string,
	timeout time.Duration) error {
	backoff := retry.NewExponentialBackoff(sendENIStateChangeBackoffMin, sendENIStateChangeBackoffMax,
		sendENIStateChangeBackoffJitter, sendENIStateChangeBackoffMultiple)
	ctx, cancel := context.WithTimeout(parentCtx, timeout)
	defer cancel()

	err := retry.RetryWithBackoffCtx(ctx, backoff, func() error {
		sendErr := udevWatcher.sendENIStateChange(macAddress)
		if sendErr != nil {
			if _, ok := sendErr.(*unmanagedENIError); ok {
				log.Debugf("Unable to send state change for unmanaged ENI: %v", sendErr)
				return sendErr
			}
			// Not unmanagedENIError. Stop retrying when this happens
			return apierrors.NewRetriableError(apierrors.NewRetriable(false), sendErr)
		}

		return nil
	})

	if err != nil {
		return err
	}
	// RetryWithBackoffCtx returns nil when the context is cancelled. Check if there was
	// a timeout here. TODO: Fix RetryWithBackoffCtx to return ctx.Err() on context Done()
	if err = ctx.Err(); err != nil {
		return errors.Wrapf(err,
			"udev watcher send ENI state change: timed out waiting for eni '%s' in state", macAddress)
	}

	return nil
}
func (udevWatcher *UdevWatcher) sendENIStateChangeWithRetries(parentCtx context.Context,
	macAddress string,
	timeout time.Duration) error {
	backoff := retry.NewExponentialBackoff(sendENIStateChangeBackoffMin, sendENIStateChangeBackoffMax,
		sendENIStateChangeBackoffJitter, sendENIStateChangeBackoffMultiple)
	ctx, cancel := context.WithTimeout(parentCtx, timeout)
	defer cancel()

	err := retry.RetryWithBackoffCtx(ctx, backoff, func() error {
		sendErr := udevWatcher.sendENIStateChange(macAddress)
		if sendErr != nil {
			if _, ok := sendErr.(*unmanagedENIError); ok {
				log.Debugf("Unable to send state change for unmanaged ENI: %v", sendErr)
				return sendErr
			}
			// Not unmanagedENIError. Stop retrying when this happens
			return apierrors.NewRetriableError(apierrors.NewRetriable(false), sendErr)
		}

		return nil
	})

	if err != nil {
		return err
	}
	// RetryWithBackoffCtx returns nil when the context is cancelled. Check if there was
	// a timeout here. TODO: Fix RetryWithBackoffCtx to return ctx.Err() on context Done()
	if err = ctx.Err(); err != nil {
		return errors.Wrapf(err,
			"udev watcher send ENI state change: timed out waiting for eni '%s' in state", macAddress)
	}

	return nil
}
// sendENIStateChangeWithRetries invokes the sendENIStateChange method, with backoff and
// retries. Retries are only effective if sendENIStateChange returns an unmanagedENIError.
// We're effectively waiting for the ENI attachment message from ACS for a network device
// at this point of time.