net: split eth_mac_addr for better error handling
When we set mac address, software mac address in system and hardware mac address all need to be updated. Current eth_mac_addr() doesn't allow callers to implement error handling nicely. This patch split eth_mac_addr() to prepare part and real commit part, then we can prepare first, and try to change hardware address, then do the real commit if hardware address is set successfully. Signed-off-by: Stefan Hajnoczi <stefanha@gmail.com> Signed-off-by: Amos Kong <akong@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
40cbfc3707
commit
fa0879e37b
2 changed files with 37 additions and 6 deletions
|
@ -40,6 +40,8 @@ extern int eth_header_cache(const struct neighbour *neigh, struct hh_cache *hh,
|
|||
extern void eth_header_cache_update(struct hh_cache *hh,
|
||||
const struct net_device *dev,
|
||||
const unsigned char *haddr);
|
||||
extern int eth_prepare_mac_addr_change(struct net_device *dev, void *p);
|
||||
extern void eth_commit_mac_addr_change(struct net_device *dev, void *p);
|
||||
extern int eth_mac_addr(struct net_device *dev, void *p);
|
||||
extern int eth_change_mtu(struct net_device *dev, int new_mtu);
|
||||
extern int eth_validate_addr(struct net_device *dev);
|
||||
|
|
|
@ -271,6 +271,36 @@ void eth_header_cache_update(struct hh_cache *hh,
|
|||
}
|
||||
EXPORT_SYMBOL(eth_header_cache_update);
|
||||
|
||||
/**
|
||||
* eth_prepare_mac_addr_change - prepare for mac change
|
||||
* @dev: network device
|
||||
* @p: socket address
|
||||
*/
|
||||
int eth_prepare_mac_addr_change(struct net_device *dev, void *p)
|
||||
{
|
||||
struct sockaddr *addr = p;
|
||||
|
||||
if (!(dev->priv_flags & IFF_LIVE_ADDR_CHANGE) && netif_running(dev))
|
||||
return -EBUSY;
|
||||
if (!is_valid_ether_addr(addr->sa_data))
|
||||
return -EADDRNOTAVAIL;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(eth_prepare_mac_addr_change);
|
||||
|
||||
/**
|
||||
* eth_commit_mac_addr_change - commit mac change
|
||||
* @dev: network device
|
||||
* @p: socket address
|
||||
*/
|
||||
void eth_commit_mac_addr_change(struct net_device *dev, void *p)
|
||||
{
|
||||
struct sockaddr *addr = p;
|
||||
|
||||
memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
|
||||
}
|
||||
EXPORT_SYMBOL(eth_commit_mac_addr_change);
|
||||
|
||||
/**
|
||||
* eth_mac_addr - set new Ethernet hardware address
|
||||
* @dev: network device
|
||||
|
@ -283,13 +313,12 @@ EXPORT_SYMBOL(eth_header_cache_update);
|
|||
*/
|
||||
int eth_mac_addr(struct net_device *dev, void *p)
|
||||
{
|
||||
struct sockaddr *addr = p;
|
||||
int ret;
|
||||
|
||||
if (!(dev->priv_flags & IFF_LIVE_ADDR_CHANGE) && netif_running(dev))
|
||||
return -EBUSY;
|
||||
if (!is_valid_ether_addr(addr->sa_data))
|
||||
return -EADDRNOTAVAIL;
|
||||
memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
|
||||
ret = eth_prepare_mac_addr_change(dev, p);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
eth_commit_mac_addr_change(dev, p);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(eth_mac_addr);
|
||||
|
|
Loading…
Reference in a new issue