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

Add BGP datapath interface and implement goBGP integration #6447

Merged
merged 1 commit into from
Jun 26, 2024

Conversation

hongliangl
Copy link
Contributor

@hongliangl hongliangl commented Jun 14, 2024

This commit introduces an interface defining methods for managing a BGP
(Border Gateway Protocol) process. Currently, only the goBGP implementation
is available, but more implementations might be added in the future.

Required by #6203

@hongliangl hongliangl added this to the Antrea v2.1 release milestone Jun 14, 2024
@hongliangl hongliangl added the area/transit/bgp Issues or PRs related to BGP support. label Jun 14, 2024
@hongliangl hongliangl force-pushed the 20240614-bgp-datapath branch 3 times, most recently from adf9e48 to 9a7d373 Compare June 19, 2024 07:08
Copy link
Member

@tnqn tnqn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hongliangl I was going to review the PR but found there is no description about what it does and how it does it, to build my expectation on the code, the same for the dependent PR #6203. Could you write a summary for reviewers to better understand the code? See the example.

@hongliangl hongliangl force-pushed the 20240614-bgp-datapath branch 2 times, most recently from 5cc3dac to 5db701e Compare June 20, 2024 06:41
@hongliangl
Copy link
Contributor Author

@hongliangl I was going to review the PR but found there is no description about what it does and how it does it, to build my expectation on the code, the same for the dependent PR #6203. Could you write a summary for reviewers to better understand the code? See the example.

Done, but not sure if the commit message could provide enough information. Please tell me if you need more information that is not covered by the commit message.

@hongliangl hongliangl requested a review from tnqn June 20, 2024 06:42
pkg/agent/bgp/engine/gobgp.go Outdated Show resolved Hide resolved
pkg/agent/bgp/engine/gobgp.go Outdated Show resolved Hide resolved
pkg/agent/bgp/engine/gobgp.go Outdated Show resolved Hide resolved
pkg/agent/bgp/engine/gobgp.go Outdated Show resolved Hide resolved
pkg/agent/bgp/engine/gobgp.go Outdated Show resolved Hide resolved
pkg/agent/bgp/engine/gobgp.go Outdated Show resolved Hide resolved
pkg/agent/bgp/engine/logs.go Outdated Show resolved Hide resolved
@tnqn
Copy link
Member

tnqn commented Jun 20, 2024

Please update PR description and link to issue.

Copy link
Contributor

@antoninbas antoninbas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't reviewed this in-depth yet (I will give a round of review after Quan's initial comments are addressed), but I have a high-level comment about the file organization. It seems that having the engine sub-directory is not providing much value. I was picturing something like this:

pkg/agent/bgp/
    # Interface used by Antrea, independent of actual BGP implementation
    interface.go
    # Utility functions / objects which are independent of the actual BGP implementation
    utils/
    # Implementation of the interface based on gobgp
    gobgp/

@hongliangl
Copy link
Contributor Author

I haven't reviewed this in-depth yet (I will give a round of review after Quan's initial comments are addressed), but I have a high-level comment about the file organization. It seems that having the engine sub-directory is not providing much value. I was picturing something like this:

pkg/agent/bgp/
    # Interface used by Antrea, independent of actual BGP implementation
    interface.go
    # Utility functions / objects which are independent of the actual BGP implementation
    utils/
    # Implementation of the interface based on gobgp
    gobgp/

Much better! Will refactor.

@hongliangl
Copy link
Contributor Author

Please update PR description and link to issue.

Will do.

@hongliangl hongliangl force-pushed the 20240614-bgp-datapath branch 2 times, most recently from 8578e48 to d950832 Compare June 21, 2024 10:43
@hongliangl hongliangl mentioned this pull request Jun 21, 2024
4 tasks
pkg/agent/bgp/interface.go Outdated Show resolved Hide resolved
pkg/agent/bgp/gobgp/gobgp.go Outdated Show resolved Hide resolved
Comment on lines 99 to 100
if peer.Transport != nil {
peerStatus.Port = int32(peer.GetTransport().GetRemotePort())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think you should mix "styles" for accessing fields, e.g., peer.Transport vs peer.GetTransport

You may be able to use something like this:

if transport := peer.GetTransport(); transport != nil {

}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another note: I don't know in which conditions these fields (e.g., Transport) can be nil, but what is the behavior we want in this case?

Edit: looking at the gobgp code, it seems that these fields are always populated when listing peers. See https://github.com/osrg/gobgp/blob/0148e2d22dcf40655d2b75c6f40bf49a378c4740/pkg/config/oc/util.go#L437. The fact that they are pointers is probably for configuration only. We can keep the nil checks but we should add a comment.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think you should mix "styles" for accessing fields

Thanks for pointing out this

Edit: looking at the gobgp code, it seems that these fields are always populated when listing peers. See https://github.com/osrg/gobgp/blob/0148e2d22dcf40655d2b75c6f40bf49a378c4740/pkg/config/oc/util.go#L437. The fact that they are pointers is probably for configuration only. We can keep the nil checks but we should add a comment.

You are right. All pointer fields are not nil when peers are listed. If so, I think we could remove the nil checks, but it seems that it is harmless and safe to reserve them. Not sure which is better.

Comment on lines 254 to 296
if peerConfig.MultihopTTL != nil && *peerConfig.MultihopTTL != bgp.DefaultBGPMultihopTTL {
peer.EbgpMultihop = &gobgpapi.EbgpMultihop{
Enabled: true,
MultihopTtl: uint32(*peerConfig.MultihopTTL),
}
}
if peerConfig.GracefulRestartTimeSeconds != nil {
peer.GracefulRestart = &gobgpapi.GracefulRestart{
Enabled: true,
RestartTime: uint32(*peerConfig.GracefulRestartTimeSeconds),
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you clarify why MultihopTTL and GracefulRestartTimeSeconds are treated differently. In particular, we only set the MultihopTTL if it's not set to the default value, but we don't do the same thing for GracefulRestartTimeSeconds. Same question for GetPeers above.

My opinion is that we should only check for nil, not for the default. There is no harm in setting it explicitly to the default, and it makes the code easier to read / maintain.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you clarify why MultihopTTL and GracefulRestartTimeSeconds are treated differently. In particular, we only set the MultihopTTL if it's not set to the default value, but we don't do the same thing for GracefulRestartTimeSeconds. Same question for GetPeers above.

My bad. They should be treated in the same way. The MultihopTTL and GracefulRestartTimeSeconds are always set since they have default values. Not sure if we should do the nil checks for these two fields, but it is harmless to do so. It seems that it is a convention for pointer field to do nil check even it has a default value (I saw such usage in other projects).

Comment on lines 249 to 291
if peerConfig.Port != nil {
peer.Transport = &gobgpapi.Transport{
RemotePort: uint32(*peerConfig.Port),
}
}
if peerConfig.MultihopTTL != nil && *peerConfig.MultihopTTL != bgp.DefaultBGPMultihopTTL {
peer.EbgpMultihop = &gobgpapi.EbgpMultihop{
Enabled: true,
MultihopTtl: uint32(*peerConfig.MultihopTTL),
}
}
if peerConfig.GracefulRestartTimeSeconds != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless I am mistaken, peerConfig.Port, peerConfig.MultihopTTL, peerConfig.GracefulRestartTimeSeconds will always be set at this point, because the default value will be populated by the apiserver? That being said it may be good to keep the nil checks. cc @tnqn

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless I am mistaken, peerConfig.Port, peerConfig.MultihopTTL, peerConfig.GracefulRestartTimeSeconds will always be set at this point, because the default value will be populated by the apiserver?

You are right, and it seems that it is a convention to do the nil checks even when the pointer fields have default values (not very sure about that).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally I would prefer writing code more precisely, i.e. if it should never be nil, then do not handle nil case. It helps making code clean and improves test coverage. For user inputs or values got from external system which is not under control, I would prefer validating them in the first place (e.g. the public functions) and skip validating them repeatedly in private functions.

But I see such error or nil check often too. If it's harmless, I don't have strong opinion.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW, if these values are really nil, and we skip setting the corresponding gobpp parameters, will there be a problem?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe that if these values are nil, gobgp will use the default behavior (default transport port value, multihop disabled, graceful restart disabled).
I think the current version of the code is ok. But we could also return an error in AddPeer / UpdatePeer if any required field is missing. The "problem" is that the interface here is tightly coupled to the BGPPolicy CRD. When a CR is created through the apiserver, all these fields should be defaulted and should not be nil, but is it a good thing to rely on this when implementing this interface, even if the BGPPolicy controller will be the only consumer of the interface?
I am fine with returning an error if any of these fields is nil. Realistically , this only matters if we have multiple implementations of the interface, and we want to try to achieve the same behavior across all of them, without having to introduce duplicate defaulting logic here (as it should always be provided by the CRD).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW, if these values are really nil, and we skip setting the corresponding gobpp parameters, will there be a problem?

As @antoninbas said, gobgp will use the default values. The corresponding code is here: https://github.com/osrg/gobgp/blob/0148e2d22dcf40655d2b75c6f40bf49a378c4740/pkg/config/oc/default.go#L62.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the current version of the code is ok. But we could also return an error in AddPeer / UpdatePeer if any required field is missing.

Will add the checks for required fields like peer address and ASN.

go.mod Outdated Show resolved Hide resolved
pkg/agent/bgp/interface.go Outdated Show resolved Hide resolved
pkg/agent/bgp/interface.go Outdated Show resolved Hide resolved
pkg/agent/bgp/interface.go Show resolved Hide resolved
@hongliangl hongliangl force-pushed the 20240614-bgp-datapath branch 2 times, most recently from 163d8f9 to faab6f4 Compare June 24, 2024 10:44
pkg/agent/bgp/gobgp/gobgp.go Outdated Show resolved Hide resolved
pkg/agent/bgp/gobgp/gobgp.go Outdated Show resolved Hide resolved
pkg/agent/bgp/gobgp/gobgp.go Outdated Show resolved Hide resolved
pkg/agent/bgp/gobgp/gobgp.go Show resolved Hide resolved
test/integration/agent/gobgp_test.go Outdated Show resolved Hide resolved
test/integration/agent/gobgp_test.go Outdated Show resolved Hide resolved
pkg/agent/bgp/gobgp/gobgp.go Outdated Show resolved Hide resolved
test/integration/agent/gobgp_test.go Outdated Show resolved Hide resolved
@hongliangl hongliangl force-pushed the 20240614-bgp-datapath branch 3 times, most recently from 7b39dae to a108491 Compare June 25, 2024 05:51
Copy link
Member

@tnqn tnqn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM overall

pkg/agent/bgp/gobgp/gobgp.go Outdated Show resolved Hide resolved
pkg/agent/bgp/gobgp/gobgp.go Outdated Show resolved Hide resolved
pkg/agent/bgp/gobgp/gobgp.go Outdated Show resolved Hide resolved
test/integration/agent/gobgp_test.go Outdated Show resolved Hide resolved
test/integration/agent/gobgp_test.go Outdated Show resolved Hide resolved
go.mod Outdated Show resolved Hide resolved
Copy link
Member

@tnqn tnqn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM once the go mod comment is addressed

This commit introduces an interface defining methods for managing a BGP
(Border Gateway Protocol) process. Currently, only the goBGP implementation
is available, but more implementations might be added in the future.

Signed-off-by: Hongliang Liu <lhongliang@vmware.com>
@hongliangl
Copy link
Contributor Author

LGTM once the go mod comment is addressed

Done. Sorry for forgetting to address the go mod comment.

Copy link
Contributor

@antoninbas antoninbas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@antoninbas antoninbas added the action/release-note Indicates a PR that should be included in release notes. label Jun 26, 2024
@antoninbas
Copy link
Contributor

/skip-all

The code is not being used yet, so tests won't reveal anything

@antoninbas antoninbas merged commit 3eefd41 into antrea-io:main Jun 26, 2024
51 of 58 checks passed
antoninbas added a commit to antoninbas/antrea that referenced this pull request Jun 26, 2024
PRs antrea-io#6447 and antrea-io#6477 got merged around the same time, and the mock file
for the BGP interface was not generated using the latest mockgen
version.

Signed-off-by: Antonin Bas <antonin.bas@broadcom.com>
antoninbas added a commit that referenced this pull request Jun 27, 2024
PRs #6447 and #6477 got merged around the same time, and the mock file
for the BGP interface was not generated using the latest mockgen
version.

Signed-off-by: Antonin Bas <antonin.bas@broadcom.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
action/release-note Indicates a PR that should be included in release notes. area/transit/bgp Issues or PRs related to BGP support.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants