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 mac assigning to network base connection #893

Merged
merged 6 commits into from
Dec 5, 2023

Conversation

jcronenberg
Copy link
Contributor

Problem

It's not possible to assign a mac address to network connections

Solution

Add a property mac_address to base connection and also to NetworkConnection inside settings to allow setting of custom mac addresses.

Note: Currently for simplicity sake it just stores it as String all around, but with this draft I also wanted to start a discussion on what agama should use to store the mac address inside BaseConnection. String is of course the simplest, but doesn't perform any validation before sending it to NetworkManager, so the result is a pretty non explanatory error that the connection couldn't be added, because NetworkManager rejects any invalid macs of course. Let me know what you would prefer 🙂 (adjustments to the type shouldn't be to much work so no worries if I should change it)

Testing

  • Modified existing unit tests
  • Tested manually

@jcronenberg jcronenberg changed the title Add mac assigning to base connection Add mac assigning to network base connection Nov 29, 2023
@coveralls
Copy link

coveralls commented Nov 29, 2023

Coverage Status

coverage: 75.009% (+0.01%) from 74.998%
when pulling 4ec3314 on jcronenberg:general-mac-address
into 2c46c58 on openSUSE:master.

@imobachgs
Copy link
Contributor

Hi @jcronenberg. First of all, thanks! And now, let's review the approach.

I prefer using some MAC address type. @teclator suggested using macaddr, which looks simple enough, but we are open to other options. However, using a String could be an acceptable temporary solution.

However, if the value is not mandatory, I would go with an Option (Option<MacAddr> or Option<String>). I would avoid using an empty string to represent that there is no address.

@jcronenberg
Copy link
Contributor Author

I prefer using some MAC address type. @teclator suggested using macaddr, which looks simple enough, but we are open to other options. However, using a String could be an acceptable temporary solution.

Alright I tend to agree, so I'll look into using that crate for the mac address type.

However, if the value is not mandatory, I would go with an Option (Option<MacAddr> or Option<String>). I would avoid using an empty string to represent that there is no address.

When going the MacAddr type route I agree, wrapping it inside an Option probably makes the most sense. However for String I found it to be unnecessarily complex because in the end the None option would have to be mapped to an empty string anyway because NetworkManager requires this setting with an empty string to overwrite any already set mac address.

@imobachgs
Copy link
Contributor

When going the MacAddr type route I agree, wrapping it inside an Option probably makes the most sense. However for String I found it to be unnecessarily complex because in the end the None option would have to be mapped to an empty string anyway because NetworkManager requires this setting with an empty string to overwrite any already set mac address.

IMHO the Option represents the reality better. I like to think about this model as backend-agnostic, so the fact that we need to map it to a string for NetworkManager should not drive our design.

@jcronenberg
Copy link
Contributor Author

When going the MacAddr type route I agree, wrapping it inside an Option probably makes the most sense. However for String I found it to be unnecessarily complex because in the end the None option would have to be mapped to an empty string anyway because NetworkManager requires this setting with an empty string to overwrite any already set mac address.

IMHO the Option represents the reality better. I like to think about this model as backend-agnostic, so the fact that we need to map it to a string for NetworkManager should not drive our design.

I think for pretty much all backends this would be the case, but anyway it doesn't really matter.

@jcronenberg
Copy link
Contributor Author

jcronenberg commented Nov 30, 2023

I have updated the PR with how I would envision it to work with a dedicated MAC type. Though I am unsure if the model is now also too NM agnostic for your liking.

Comment on lines 229 to 231
Value::new(match &conn.base.mac_address {
Some(mac) => mac.to_string(),
None => "".to_string(),
Copy link
Contributor

Choose a reason for hiding this comment

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

because of this, maybe we could place mac_address_string() into BaseConnection

Copy link
Contributor

@cfconrad cfconrad left a comment

Choose a reason for hiding this comment

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

LGTM

@jcronenberg jcronenberg marked this pull request as ready for review November 30, 2023 16:25
Copy link
Contributor

@imobachgs imobachgs left a comment

Choose a reason for hiding this comment

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

When I proposed an Option I was not aware that it was not a simple address, but that you were defining your own enum. Sorry if I overlooked something.

In that case, the None variant could be part of your enum, so you would not need to cope with that case anymore and you could simplify the code.

And that _string method would not be needed at all.

/// Custom mac-address
#[dbus_interface(property)]
pub async fn mac_address(&self) -> String {
self.get_connection().await.base().mac_address_string()
Copy link
Contributor

Choose a reason for hiding this comment

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

For better encapsulation, please do not call base() from outside the struct. Actually, I think base() should be private.

I would implement mac_address() in Connection directly.

}

#[derive(Debug, Default, Clone)]
pub struct BaseConnection {
pub id: String,
pub uuid: Uuid,
pub mac_address: Option<MacAddress>,
Copy link
Contributor

Choose a reason for hiding this comment

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

When I proposed using an Option, I thought you would have the macaddr::MacAddr struct inside. But I see that it is more complex as you are defining an enum (MacAddress). To make things easier, why not just add a MacAddress::None (feel free to find a better name, please)? So you do not need to cope with the Option anymore.

Actually, you could convert that value to an empty string.

}
}

pub fn set_mac_address(&mut self, mac_address: &str) -> Result<(), InvalidMacAddress> {
Copy link
Contributor

Choose a reason for hiding this comment

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

This one looks counter-intuitive to me. Why do I need to convert a MacAddress to a string? Not to mention the fact that an empty string means None. If you add the None variant to the MacAddress enum, well, problem solved.

If you continue with the Option approach, I would 1) pass an option or 2) have a set_mac_address and a unset_mac_address.

fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"preserve" => Ok(Self::Preserve),
"permanent" => Ok(Self::Preserve),
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is "permanent" converted to Preserve?

match s {
"preserve" => Ok(Self::Preserve),
"permanent" => Ok(Self::Preserve),
"random" => Ok(Self::Permanent),
Copy link
Contributor

@imobachgs imobachgs Dec 1, 2023

Choose a reason for hiding this comment

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

Why are "random" and "stable" converted to Permanent?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oops must have been some lazy copy pasting 😄

self.base().mac_address.to_string()
}

pub fn set_mac_address(&mut self, mac_address: &str) -> Result<(), InvalidMacAddress> {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
pub fn set_mac_address(&mut self, mac_address: &str) -> Result<(), InvalidMacAddress> {
pub fn set_mac_address(&mut self, mac_address: MacAddress) {

}

pub fn set_mac_address(&mut self, mac_address: &str) -> Result<(), InvalidMacAddress> {
self.base_mut().mac_address = MacAddress::from_str(mac_address)?;
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
self.base_mut().mac_address = MacAddress::from_str(mac_address)?;
self.base_mut().mac_address = mac_address;


pub fn set_mac_address(&mut self, mac_address: &str) -> Result<(), InvalidMacAddress> {
self.base_mut().mac_address = MacAddress::from_str(mac_address)?;
Ok(())
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
Ok(())

@imobachgs imobachgs merged commit 52dc7a3 into agama-project:master Dec 5, 2023
1 check passed
@jcronenberg jcronenberg deleted the general-mac-address branch December 5, 2023 17:16
@imobachgs imobachgs mentioned this pull request Feb 12, 2024
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