-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
prioritise thunderbolt over WIFI #41 #47
Conversation
This is awesome! First proper PR, congrats! Code looks great, only one very minor thing for consistency across the codebase, instead of |
Will change. |
Also don't we need to add |
My bad! We do! I just installed it locally and forgot about setup.py! Will update the whole thing and give you a better one! |
|
||
def get_network_interfaces(self): | ||
interfaces = netifaces.interfaces() | ||
if psutil.system() == "Darwin": # macOS |
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.
Make this if psutil.MACOS:
and remove the 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.
Beat me to it!
Just added an integration test for discovery. Already coming in useful, we'll see if it still passes after your changes. |
I guess setting up netifaces dependency failed?! |
f554ae0
to
0222b2e
Compare
I just quickly tested this myself locally. For me, the interface name does not begin with # before thunderbolt connected
>>> netifaces.interfaces()
['lo0', 'gif0', 'stf0', 'anpi0', 'anpi1', 'anpi2', 'en4', 'en5', 'en6', 'en1', 'en2', 'en3', 'bridge0', 'ap1', 'en0', 'awdl0', 'llw0', 'utun0', 'utun1', 'utun2', 'utun3', 'utun4', 'utun5', 'utun6', 'utun7', 'utun8', 'utun9']
# after thunderbolt connected
>>> netifaces.interfaces()
['lo0', 'gif0', 'stf0', 'anpi0', 'anpi1', 'anpi2', 'en4', 'en5', 'en6', 'en1', 'en2', 'en3', 'bridge0', 'ap1', 'en0', 'awdl0', 'llw0', 'utun0', 'utun1', 'utun2', 'utun3', 'utun4', 'utun5', 'utun6', 'utun7', 'utun8', 'utun9', 'en11', 'en16'] As you can see, |
Eventually we should support automatically upgrading to the best interface available (in this case thunderbolt) - see #51. We can implement this later though, for now this is great. |
This makes better sense, @AlexCheema. |
Just to clarify, this still needs to be fixed / tested: #47 (comment) |
Update:
@AlexCheema, I wrote a test script and it returned: Please review this. |
print(f"Other interfaces: {other_interfaces}") | ||
|
||
# Prioritize Thunderbolt, then WiFi, then others | ||
return thunderbolt_interfaces + wifi_interfaces + other_interfaces |
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.
Beautiful code. love this
Have you got a thunderbolt cable to test this with? I don't think this works in its current state. This is what
|
I had another look and generally I don't think this is doing what we want it to do. I think what we need to do here:
|
Did:
@AlexCheema, wrote a small test script that simulates receiving a broadcast from a peer. And to see whether it keeps track of priority and change when a better one comes. Here is the output from the test: |
@itsknk can you commit the test too? and add some assertions so it's a proper test would be great |
Done @AlexCheema |
@@ -30,11 +32,42 @@ def __init__(self, node_id: str, node_port: int, listen_port: int, broadcast_por | |||
self.listen_port = listen_port | |||
self.broadcast_port = broadcast_port if broadcast_port is not None else listen_port | |||
self.broadcast_interval = broadcast_interval | |||
self.known_peers: Dict[str, Tuple[GRPCPeerHandle, float, float]] = {} | |||
self.known_peers: Dict[str, Tuple[GRPCPeerHandle, float, float, int]] = {} # Added priority |
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 is there a comment here?
if not interface_name: | ||
continue | ||
|
||
priority = self.get_interface_priority(interface_name, interface_type, hardware) |
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.
This is a pure function. Move it outside of the class
import json | ||
import psutil | ||
import time | ||
|
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.
Once you move this off the class, get rid of the duplicate definition here
self.broadcast_task = None | ||
self.listen_task = None | ||
self.cleanup_task = None | ||
|
||
def get_network_interfaces(self): |
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.
Same here, this is a pure function so move it outside of the class
from typing import List, Dict, Callable, Tuple, Coroutine | ||
from ..discovery import Discovery | ||
from ..peer_handle import PeerHandle | ||
from .grpc_peer_handle import GRPCPeerHandle | ||
from exo.topology.device_capabilities import DeviceCapabilities, device_capabilities, UNKNOWN_DEVICE_CAPABILITIES | ||
from exo import DEBUG_DISCOVERY | ||
|
||
def get_interface_priority(interface_name, interface_type='', hardware=''): |
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.
types please
else: | ||
return 0 | ||
|
||
def get_network_interfaces(): |
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.
return type
print(f"Error in broadcast presence: {e}") | ||
import traceback | ||
print(traceback.format_exc()) | ||
if DEBUG_DISCOVERY >= 2: print(f"Error updating or accessing interfaces: {e}") |
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 did the message change?
if peer_id in self.known_peers: | ||
_, _, _, current_priority = self.known_peers[peer_id] | ||
if new_priority > current_priority: | ||
await self.reconnect_peer(peer_id, peer_host, peer_port, new_priority, device_capabilities) |
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.
discovery is not responsible for connecting to peers, it just discovers them. connecting should happen in the standard_node.py
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.
this requires a bit of a refactor to do properly, I'm focusing on linux fixes right now but if you have any questions async, leave a comment on this PR and tag me
Hey @AlexCheema, yeah it does look a little complex. After some understanding, I thought of some steps. Please do verify these, and let me know if I'm on the right track.
|
First of all, thanks a lot for these contributions - experimentation helps a lot to inform future decisions even if things don't get merged. I end up throwing away most the code I write. There have been quite a few changes since this PR (health checks, broadcast on multiple interfaces, priorities). There's now a I think this PR might need to be closed now, but I'm happy to send you a retrospective $100 bounty for your work and it helped inform some of the decisions made in the repo. If you like, we are currently setting |
For issue #41, I figured the solution could be quite simple since it already supports the Thunderbolt discovery and needs to be prioritized.
I've updated the
grpc_discovery.py
file to get this done.Changes made:
netifaces
andplatform
.get_network_interfaces
method that prioritizes Thunderbolt interfaces over WiFi on macOS.__init__
method to callget_network_interfaces
and store the result.task_broadcast_presence
to broadcast on all available interfaces, prioritizing Thunderbolt on macOS.task_listen_for_peers
to listen on all available interfaces.