-
Notifications
You must be signed in to change notification settings - Fork 367
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
Conversation
adf9e48
to
9a7d373
Compare
There was a problem hiding this 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.
5cc3dac
to
5db701e
Compare
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. |
Please update PR description and link to issue. |
There was a problem hiding this 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/
Much better! Will refactor. |
Will do. |
8578e48
to
d950832
Compare
pkg/agent/bgp/gobgp/gobgp.go
Outdated
if peer.Transport != nil { | ||
peerStatus.Port = int32(peer.GetTransport().GetRemotePort()) |
There was a problem hiding this comment.
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 {
}
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
pkg/agent/bgp/gobgp/gobgp.go
Outdated
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), | ||
} | ||
} |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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).
pkg/agent/bgp/gobgp/gobgp.go
Outdated
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 { |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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).
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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).
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
163d8f9
to
faab6f4
Compare
7b39dae
to
a108491
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM overall
a108491
to
95ad189
Compare
There was a problem hiding this 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
95ad189
to
742ceaf
Compare
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>
742ceaf
to
4e28e45
Compare
Done. Sorry for forgetting to address the go mod comment. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
/skip-all The code is not being used yet, so tests won't reveal anything |
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>
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