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

feat(evpn-bridge): netlink watcher Module #385

Merged
merged 12 commits into from
Aug 26, 2024

Conversation

atulpatel261194
Copy link
Contributor

No description provided.

@atulpatel261194 atulpatel261194 requested a review from a team as a code owner May 20, 2024 07:00
@atulpatel261194 atulpatel261194 changed the title feat(evpn-bridge): netlink watcherModule feat(evpn-bridge): netlink watcher Module May 20, 2024
pkg/netlink/eventbus/eventbus.go Outdated Show resolved Hide resolved
pkg/netlink/eventbus/eventbus.go Show resolved Hide resolved
pkg/netlink/eventbus/eventbus.go Outdated Show resolved Hide resolved

// Unsubscribe the subscriber, which delete the subscriber(all resources will be washed out)
func (s *Subscriber) Unsubscribe() {
close(s.Ch)
Copy link
Contributor

Choose a reason for hiding this comment

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

If you write to a closed channel, your program will panic, and it is possible since someone can still be writing on the line 56 to a chan.
Usually it is a responsibility of the send side to close the chan.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

chan will be closed only when we deinitialize from vendor module. there are some missing pieces in unsubscriber function . will be added in vendor module PR

Copy link
Contributor

Choose a reason for hiding this comment

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

hmmm... it might work with mutexes, but can we do better? Could WaitGroup help here?

pkg/netlink/netlink_watcher.go Outdated Show resolved Hide resolved
pkg/netlink/netlink_watcher.go Show resolved Hide resolved
pkg/netlink/netlink_watcher.go Show resolved Hide resolved
pkg/netlink/netlink_watcher.go Outdated Show resolved Hide resolved
pkg/netlink/netlink_watcher.go Outdated Show resolved Hide resolved
}

// oldgenmap old map
var oldgenmap = make(map[interface{}]interface{})
Copy link
Contributor

Choose a reason for hiding this comment

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

we have many global vars scattered here and there in this file. Could we group them within a struct, maybe even multiple structs, separated by their purpose? It is sometimes hard to follow what function can change. With usage of global vars and functions, they can change any of them. Functions could operate not on global vars, but on members of a specific struct instance

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@atulpatel261194 atulpatel261194 force-pushed the drop1.0netlinkwatcher branch 6 times, most recently from 0e3a2c1 to bcb2125 Compare May 27, 2024 10:37
pkg/netlink/netlink_watcher.go Outdated Show resolved Hide resolved
pkg/netlink/netlink_watcher.go Outdated Show resolved Hide resolved
Copy link
Contributor

@artek-koltun artek-koltun left a comment

Choose a reason for hiding this comment

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

some more notes

docker-compose.yml Outdated Show resolved Hide resolved
pkg/netlink/netlink_watcher.go Outdated Show resolved Hide resolved
pkg/netlink/netlink_watcher.go Outdated Show resolved Hide resolved
pkg/netlink/netlink_watcher.go Outdated Show resolved Hide resolved
pkg/netlink/netlink_watcher.go Outdated Show resolved Hide resolved
if strings.Contains(event[1], "route") || strings.HasPrefix(event[1], "nexthop") {
var rv *RouteStruct
var nv *NexthopStruct
if strings.Contains(event[1], "route") {
Copy link
Contributor

Choose a reason for hiding this comment

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

how do you know that you have 2 elements in event array?

Copy link
Contributor

Choose a reason for hiding this comment

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

done

Copy link
Contributor

Choose a reason for hiding this comment

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

not done. I see

if rv.Vrf.Status.VrfOperStatus == infradb.VrfOperStatusToBeDeleted {
   notifyAddDel(rv, event.Operation[2])

What does index 2 mean here? Why was it 1? Would it make sense to create a dedicated struct where we ahve 3 members and their name clearly explain what those events mean?

Copy link
Contributor

Choose a reason for hiding this comment

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

each event will have 3 operations add, update and delete, accordingly we are filling operations for each event type, so that's where we have length 3 and index 2 for delete, which already defined as constants

Copy link
Contributor

@artek-koltun artek-koltun Jul 3, 2024

Choose a reason for hiding this comment

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

For me, it is just a magic number. You might have context how indexing in this array correspond to operations, but I do not have such a context and people who come and try to understand this code, does not have this context either.
Why we cannot use?

notifyAddDel(rv, event.operations.to_delete)

Plus

The code chunk at the moment look like

if event.EventType == ROUTE || event.EventType == NEXTHOP {
var rv *RouteStruct
var nv *NexthopStruct
if event.EventType == ROUTE {
	rv, ok = v1.(*RouteStruct)
	if !ok {
		log.Printf("Netlink: Type mismatch")
		continue
	}
	if rv.Vrf.Status.VrfOperStatus == infradb.VrfOperStatusToBeDeleted {
		notifyAddDel(rv, event.Operation[2])
		delete(new_db, k1)
		delete(old_db, k1)
		continue
	}
} else if event.EventType == NEXTHOP {
	nv, ok = v1.(*NexthopStruct)
	if !ok {
		log.Printf("Netlink: Type mismatch")
		continue
	}
	if nv.Vrf.Status.VrfOperStatus == infradb.VrfOperStatusToBeDeleted {
		notifyAddDel(nv, event.Operation[2])
		delete(new_db, k1)
		delete(old_db, k1)
		continue
	}
}

Don't you have a feeling that the code in first if is very similar in the code in the second if?
Can we have an interface which would return the status, type assert to that interface once, get the status and do your actions without these duplications? Type Assert v1 to one type or another, get status and work with that? Any other means?

Copy link
Contributor

Choose a reason for hiding this comment

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

Done

Copy link
Contributor

Choose a reason for hiding this comment

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

This

switch event.EventType {
case ROUTE:
	status, ok = v1.(VrfStatusGetter)
case NEXTHOP:
	status, ok = v1.(VrfStatusGetter)
default:
}

to

status, ok := v1.(VrfStatusGetter)

Copy link
Contributor

Choose a reason for hiding this comment

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

Done

pkg/netlink/netlink_watcher.go Outdated Show resolved Hide resolved
pkg/netlink/netlink_watcher.go Outdated Show resolved Hide resolved
pkg/netlink/netlink_watcher.go Outdated Show resolved Hide resolved
pkg/netlink/netlink_watcher.go Outdated Show resolved Hide resolved
case *NexthopStruct:
return t.deepEqual(v2.(*NexthopStruct), true)
}
return true
Copy link
Contributor

Choose a reason for hiding this comment

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

so if we have v1 and v2 of different types,t hen we return true
looks suspicious

Copy link
Contributor

Choose a reason for hiding this comment

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

fixed

Copy link
Contributor

Choose a reason for hiding this comment

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

but what if v1 and v2 of the same type but not RouteStruct or NexthopStruct. It is still true

Copy link
Contributor

Choose a reason for hiding this comment

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

Done, we now check for 4 possible structs

pkg/netlink/netlink_watcher.go Outdated Show resolved Hide resolved
pkg/netlink/netlink_watcher.go Outdated Show resolved Hide resolved
if strings.Contains(event[1], "route") || strings.HasPrefix(event[1], "nexthop") {
var rv *RouteStruct
var nv *NexthopStruct
if strings.Contains(event[1], "route") {
Copy link
Contributor

@artek-koltun artek-koltun Jul 3, 2024

Choose a reason for hiding this comment

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

For me, it is just a magic number. You might have context how indexing in this array correspond to operations, but I do not have such a context and people who come and try to understand this code, does not have this context either.
Why we cannot use?

notifyAddDel(rv, event.operations.to_delete)

Plus

The code chunk at the moment look like

if event.EventType == ROUTE || event.EventType == NEXTHOP {
var rv *RouteStruct
var nv *NexthopStruct
if event.EventType == ROUTE {
	rv, ok = v1.(*RouteStruct)
	if !ok {
		log.Printf("Netlink: Type mismatch")
		continue
	}
	if rv.Vrf.Status.VrfOperStatus == infradb.VrfOperStatusToBeDeleted {
		notifyAddDel(rv, event.Operation[2])
		delete(new_db, k1)
		delete(old_db, k1)
		continue
	}
} else if event.EventType == NEXTHOP {
	nv, ok = v1.(*NexthopStruct)
	if !ok {
		log.Printf("Netlink: Type mismatch")
		continue
	}
	if nv.Vrf.Status.VrfOperStatus == infradb.VrfOperStatusToBeDeleted {
		notifyAddDel(nv, event.Operation[2])
		delete(new_db, k1)
		delete(old_db, k1)
		continue
	}
}

Don't you have a feeling that the code in first if is very similar in the code in the second if?
Can we have an interface which would return the status, type assert to that interface once, get the status and do your actions without these duplications? Type Assert v1 to one type or another, get status and work with that? Any other means?

pkg/netlink/netlink_watcher.go Outdated Show resolved Hide resolved
docker-compose.yml Outdated Show resolved Hide resolved
@mardim91
Copy link
Contributor

mardim91 commented Jul 4, 2024

Hello @artek-koltun

I have created a dedicated PR for the docker-compose fix: #390

atulpatel261194 and others added 6 commits July 9, 2024 08:39
Co-authored-by: Vemula Venkatesh <[email protected]>
Co-authored-by: Saikumar Banoth <[email protected]>
Co-authored-by: Jambekar Vishakha <[email protected]>
Co-authored-by: Dimitrios Markou <[email protected]>
Signed-off-by: atulpatel261194 <[email protected]>
Signed-off-by: Saikumar, Banoth <[email protected]>
Signed-off-by: Saikumar, Banoth <[email protected]>
Signed-off-by: Saikumar, Banoth <[email protected]>
pkg/netlink/annotatedb.go Outdated Show resolved Hide resolved
pkg/netlink/annotatedb.go Outdated Show resolved Hide resolved
pkg/netlink/netlink_watcher.go Outdated Show resolved Hide resolved
case *L2NexthopStruct:
return t.deepEqual(v2.(*L2NexthopStruct), true)
default:
return true
Copy link
Contributor

Choose a reason for hiding this comment

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

Are you sure that you want to return true, if v1 is none of the listed types?

Copy link
Contributor

Choose a reason for hiding this comment

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

yes, we deal with only the 4 structures defined.

Copy link
Contributor

Choose a reason for hiding this comment

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

and if you add a new type, it will be always true if by mistake this code is not updated?

Copy link
Contributor

Choose a reason for hiding this comment

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

when a new type is declared, one need to implement the difference check function for it, best thing is we can log in default

Copy link
Contributor

Choose a reason for hiding this comment

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

when a new type is declared, one need to implement the difference check function for it, best thing is we can log in default

best we can do here is to log an error and report that they are not equal if an unknown types are coming

Copy link
Contributor

Choose a reason for hiding this comment

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

Done

Copy link
Contributor

Choose a reason for hiding this comment

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

true is still returned

Copy link
Contributor

Choose a reason for hiding this comment

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

yes, we log and return true because don't want to handle such cases,
In case the values are equal we return true to deepcheck and we don't process it simply delete it,
same when we get unknown structs we log and return true and delete them

pkg/netlink/notify.go Outdated Show resolved Hide resolved
pkg/netlink/filter.go Outdated Show resolved Hide resolved
pkg/netlink/netlinkstate.go Outdated Show resolved Hide resolved
fdbentry.bp, _ = infradb.GetBP(bp)
}
}
Dev := fdbIP.Ifname
Copy link
Contributor

Choose a reason for hiding this comment

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

why some vars are capitilized, some not? https://google.github.io/styleguide/go/decisions.html

Copy link
Contributor

Choose a reason for hiding this comment

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

Done

Copy link
Contributor

Choose a reason for hiding this comment

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

still see some like CPs

Copy link
Contributor

Choose a reason for hiding this comment

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

Done

Copy link
Contributor

Choose a reason for hiding this comment

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

image

Please check other places

Copy link
Contributor

Choose a reason for hiding this comment

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

Done

pkg/netlink/netlinkstate.go Outdated Show resolved Hide resolved
pkg/netlink/netlinkstate.go Outdated Show resolved Hide resolved
Signed-off-by: Saikumar, Banoth <[email protected]>
pkg/netlink/common.go Outdated Show resolved Hide resolved
pkg/netlink/annotatedb.go Outdated Show resolved Hide resolved
Copy link
Contributor

@artek-koltun artek-koltun left a comment

Choose a reason for hiding this comment

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

pkg/netlink/fdb.go Show resolved Hide resolved
Inbanoth and others added 4 commits July 22, 2024 12:47
Signed-off-by: Saikumar, Banoth <[email protected]>
Signed-off-by: Saikumar, Banoth <[email protected]>
Signed-off-by: atulpatel261194 <[email protected]>
@atulpatel261194 atulpatel261194 force-pushed the drop1.0netlinkwatcher branch 2 times, most recently from fbac3d6 to bb3e67f Compare August 26, 2024 09:54
Copy link
Contributor

@artek-koltun artek-koltun left a comment

Choose a reason for hiding this comment

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

Despite the current quality disadvantages, we agreed to merge the code as is due to the time constraints. According to the agreement, the tech debt will be re-designed and addressed by the team with the highest priority.

@artek-koltun artek-koltun merged commit cbc1fba into opiproject:main Aug 26, 2024
39 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants