-
Notifications
You must be signed in to change notification settings - Fork 109
GATEWAYS-4422 - Add DumpPortMappings API to retrieve ofport and MAC address for tap interfaces #141
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
base: master
Are you sure you want to change the base?
Conversation
24eb418 to
7a2a409
Compare
ovs/openflow.go
Outdated
| // PortMapping contains the ofport number and MAC address for an interface. | ||
| type PortMapping struct { | ||
| // OfPort specifies the OpenFlow port number. | ||
| OfPort int |
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.
Suggest ofPort to maintain consistency. Ditto for macAddress
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.
Sure
ovs/openflow.go
Outdated
| mappings := make(map[string]*PortMapping) | ||
| scanner := bufio.NewScanner(bytes.NewReader(out)) | ||
|
|
||
| for scanner.Scan() { |
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 follow semantics similar to parseEach() and define your own parseEachPort() or something like that, instead of regexp?
showPrefix =[]byte("OFPT_FEATURES_REPLY")
ovs/openflow.go
Outdated
| "errors" | ||
| "fmt" | ||
| "io" | ||
| "regexp" |
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.
These may not be needed if you switch to parseEach semantics.
ovs/openflow.go
Outdated
| // portMappingPattern matches port lines from 'ovs-ofctl show' output. | ||
| // Pattern matches: " 7(interface1): addr:fe:4f:76:09:88:2b" | ||
| // or " 65534(LOCAL): addr:fe:4f:76:09:88:2b" | ||
| portMappingPattern = regexp.MustCompile(`^\s*(\d+)\(([^)]+)\):\s*addr:([a-fA-F0-9:]+)`) |
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.
Should be able to remove this.
ovs/openflow_test.go
Outdated
| } | ||
| } | ||
|
|
||
| func TestClientOpenFlowDumpPortMappingsOnlyLOCAL(t *testing.T) { |
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.
Instead of a test case specifically for LOCAL, this should be a generic one to test for a specified interface index
|
|
||
| // DumpPortMappings retrieves port mappings (ofport and MAC address) for all | ||
| // interfaces from the specified bridge. The output is parsed from 'ovs-ofctl show' command. | ||
| func (o *OpenFlowService) DumpPortMappings(bridge string) (map[string]*PortMapping, error) { |
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 would like to add one variant of this function in addition to this function. It should also be possible using another function to return the PortMapping for a single interface index provided as an input. Also, see my comment in the test section - you can modify the test accordingly.
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.
Sure.
- Added JSON tags (ofPort, macAddress) to PortMapping struct for consistency - Refactored to use parseEachPort() semantics instead of regex, following parseEach() pattern - Removed unused regexp import and portMappingPattern variable - Updated test to be generic table-driven instead of LOCAL-specific - Added DumpPortMapping (singular) function for single interface lookup - Fixed some error handling consistency, add MAC/ofport validation, and eliminate code duplication
ovs/openflow.go
Outdated
| // Find the opening parenthesis | ||
| openParen := strings.IndexByte(s, '(') | ||
| if openParen == -1 { | ||
| return fmt.Errorf("invalid port mapping format: missing opening parenthesis") |
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.
It should be sufficient to indicate invalid format for both open & close paren error cases without being too specific.
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 will simplify the error handling - any malformed line would return the generic ‘invalid port mapping format’ message, so we don’t over-specify which character is missing.
ovs/openflow.go
Outdated
| } | ||
|
|
||
| // Find the closing parenthesis | ||
| closeParen := strings.IndexByte(s[openParen:], ')') |
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.
Why not look up in s, like the openParen case? Then you won't have to add the index.
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.
Good point - that would make both ( and ) searched directly in the full string, so thers's no extra index math anymore
ovs/openflow.go
Outdated
|
|
||
| // Find "addr:" after the closing parenthesis | ||
| addrPrefix := ": addr:" | ||
| addrIdx := strings.Index(s[closeParen:], addrPrefix) |
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.
Similar comment as above
ovs/openflow.go
Outdated
| mappings := make(map[string]*PortMapping) | ||
| err = parseEachPort(out, showPrefix, func(line []byte) error { | ||
| // Check if line matches port format: " 7(interface1): addr:..." | ||
| if !bytes.Contains(line, []byte("(")) || !bytes.Contains(line, []byte("): addr:")) { |
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.
Why are all these checks needed? L445 call to UnmarshalText will do all this anyway, no?
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.
Noted. I will plan to remove them.
After UnmarshalText succeeds, we slice s[openParen+1 : closeParen] without rechecking openParen/closeParen (openflow.go, lines 432-435).
Is it acceptable to trust UnmarshalText (since it already checks parentheses), or do you want a defensive guard to skip unexpected lines?
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 an additional check is necessary. This is a pretty custom function meant only for this purpose. There won't be any other callers for this variant of UnmarshalText. UnmarshalText is supposed to do the heavy lifting including parsing etc and returning the parsed values.
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.
Understood, I will remove the redundant checks.
ovs/openflow.go
Outdated
| // PortMapping contains the ofport number and MAC address for an interface. | ||
| type PortMapping struct { | ||
| // OfPort specifies the OpenFlow port number. | ||
| OfPort int `json:"ofPort"` |
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.
Why json encodings? I was suggesting changing the var name from OfPort to ofPort.
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 initially interpreted your “ofPort/macAddress” note as wanting camelCase JSON keys, so I added tags instead of renaming the exported fields. Will make the suggested changes.
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.
Current code uses ofPort/macAddress (lowercase) in PortMapping (openflow.go, lines 75-82). This breaks external callers who expect PortMapping.OfPort.
Could you confirm if we were supposed to only rename the exported fields to OfPort/MACAddress, or actually hide them? Should we revert to exported fields and have camelCase in comments/docs instead?
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.
Was suggesting a similar case as the type structures at L62 and L70. Since this is a new type definition, I am curious which external callers (other than test) it breaks.
If test isn't able to work with this case, we can ignore this 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.
Got it.
- Removeed JSON tags and use unexported fields (ofPort, macAddress) following L62-66 pattern - Removed redundant format checks in callback (UnmarshalText handles all validation) - Fixed string slicing to search full string for closeParen and addrIdx - Consolidated error messages to generic 'invalid port mapping format'
| return nil | ||
| } | ||
|
|
||
| // Extract interface name from the validated line for map key |
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.
You can move parsing of interface name to UnmarshalText as well. You may need to declare another structure to accomplish this e.g.
type PortAttr struct {
// ofPort specifies the OpenFlow port number.
ofPort int
// macAddress specifies the MAC address of the interface.
macAddress string
}
type PortMapping struct {
portAttr PortAttr
ifName string
}
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.
Noted.
• Adds new DumpPortMappings method to OpenFlowService for retrieving port mappings
• Parses ovs-ofctl show output to extract ofport numbers and MAC addresses
• Filters results to include only tap interfaces and LOCAL port
• Returns map of interface names to PortMapping structs containing ofport and MAC
• Includes comprehensive test coverage with 5 test cases