Forum: Mikrocontroller und Digitale Elektronik lwip MAC Adresse ändern


von user (Gast)


Lesenswert?

Guten Morgen,

auf meinem Mikrocontroller läuft eine Ethernetkommunikation mit dem lwip 
Stack. In der Applikation soll die MAC Adresse abgeändert werden können.
Für die Initialisierung der MAC Adresse gibt es eine Funktion mit dem 
Namen
"low_level_init".

Ausschnitt von der Funktion "low_level_init":
1
static void
2
low_level_init(struct netif *netif)
3
{
4
  XMC_ETH_MAC_PORT_CTRL_t port_control;
5
  XMC_GPIO_CONFIG_t gpio_config;
6
7
  /* set MAC hardware address length */
8
  netif->hwaddr_len = ETHARP_HWADDR_LEN;
9
10
  /* set MAC hardware address */
11
  netif->hwaddr[0] =  MAC_ADDR0;
12
  netif->hwaddr[1] =  MAC_ADDR1;
13
  netif->hwaddr[2] =  MAC_ADDR2;
14
  netif->hwaddr[3] =  MAC_ADDR3;
15
  netif->hwaddr[4] =  MAC_ADDR4;
16
  netif->hwaddr[5] =  MAC_ADDR5;
17
18
...

Die MAC Adresse liegt als define in der Datei ethernetif.c vor wo sich 
auch die obige Funktion befindet. Wie könnte eine andere MAC Adresse von 
der Hauptapplikation dieser Funktion übergeben werden?

von TK (Gast)


Lesenswert?

>Wie könnte eine andere MAC Adresse von
>der Hauptapplikation dieser Funktion übergeben werden?
Evtl. indem man nach Aufruf der oben gezeigen Funktion
das Array hwaddr[0]..[5] nochmal neu belegt.
ODER
Indem man die Funktion so abändert, dass eine MAC-Adr als Parameter
an diese übergeben wird. Und dann werden nicht mehr die DEFINES
zugewiesen, sondern der Übergabeparameter.

Gruß
TK

von Matthias F. (frank91)


Lesenswert?

Der Beitrag ist schon etwas älter.
Ich hatte allerdings gerade das selbe Problem.
Da hier noch kein Beispiel gezeigt wurde poste ich hier nun eines.

>>Wie könnte eine andere MAC Adresse von
>>der Hauptapplikation dieser Funktion übergeben werden?
> Evtl. indem man nach Aufruf der oben gezeigen Funktion
> das Array hwaddr[0]..[5] nochmal neu belegt.

Nach dem Initialisieren, also zur Laufzeit die Mac Adresse ändern ist 
denke ich schlecht. Ich weiß nicht ob DHCP dann richtig arbeiten kann.

Funktionierende Lösung:
1
static void low_level_init(struct netif *netif)
2
{ 
3
  uint32_t regvalue = 0;
4
  HAL_StatusTypeDef hal_eth_init_status;
5
  
6
/* Init ETH */
7
8
   uint8_t MACAddr[6] ;
9
  heth.Instance = ETH;
10
  heth.Init.AutoNegotiation = ETH_AUTONEGOTIATION_DISABLE;
11
  heth.Init.Speed = ETH_SPEED_100M;
12
  heth.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
13
  heth.Init.PhyAddress = DP83848_PHY_ADDRESS;
14
  MACAddr[0] = 0x00;
15
  MACAddr[1] = 0x80;
16
  MACAddr[2] = 0xE1;
17
  MACAddr[3] = 0x00;
18
  MACAddr[4] = 0x00;
19
  MACAddr[5] = 0x00;
20
  heth.Init.MACAddr = &MACAddr[0];
21
  heth.Init.RxMode = ETH_RXPOLLING_MODE;
22
  heth.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;
23
  heth.Init.MediaInterface = ETH_MEDIA_INTERFACE_MII;
24
25
  /* USER CODE BEGIN MACADDRESS */
26
  MACAddr[0] = EEPROM_Daten.macAdresse[0];
27
  MACAddr[1] = EEPROM_Daten.macAdresse[1];
28
  MACAddr[2] = EEPROM_Daten.macAdresse[2];
29
  MACAddr[3] = EEPROM_Daten.macAdresse[3];
30
  MACAddr[4] = EEPROM_Daten.macAdresse[4];
31
  MACAddr[5] = EEPROM_Daten.macAdresse[5];
32
  /* USER CODE END MACADDRESS */
33
34
  hal_eth_init_status = HAL_ETH_Init(&heth);

von Ruediger A. (Firma: keine) (rac)


Lesenswert?

uhm, wird hier etwas im Nebel gestochert?

Die MAC Adresse wird an ZWEI Stellen gebraucht:

1. Bei der Konfiguration des MAC, damit er auf die Adresse filtern kann
  (es werden, solange der MAC nicht im promiscuous mode fährt)
   nur Broadcasts (Ziel MAC ff:ff:ff:ff:ff:ff) und die MAC Adresse
   des Interfaces zum DMA Rx Ringbuffer weitergeleitet).
   Das passiert beim Standard Cortex Treiber z.B. in
   ETH_MacAddressConfig(), indem dem POD die MAC
   ins passende Register geschrieben wird.
2. Im Software Layer, damit der u.A. jedes ausgehende Paket mit der
   MAC Adresse des Interfaces prefixen kann. Das wird i.d. Regel
   in low_level_init() über netif->hwaddr gemacht.

Man muss unbedingt in beiden Stellen parallel immer dieselbe Adresse 
vorhalten. Was passiert, wenn man das nur an einer Stelle macht, ist 
eine Denkaufgabe fürs erste Semester.

In deinem Codefragment fehlt die Zuweisung in 2. oben, aber ich vermute, 
dass Du die nach  HAL_ETH_Init() machst, und zwar indem Du netif->hwaddr 
auf MACAddr setzt. Dann bist Du natürlich wieder synchron, und alles ist 
gut. Würdest Du aber das Patchen von MACAddr hinter HAL_ETH_Init aber 
vor dem Setzen von netif->hwaddr machen, würde es nicht gehen.

Man kann zur Laufzeit die MAC Adresse ändern (solange man das an beiden 
Stellen synchron macht; bei manchen MACs wird ausserdem eine 
Reiniaitliserung des MAC interfaces nötig), aber dann lassen sich 
keinerlei Annamhmen mehr über das Verhalten von momentan offenen 
Netzwerkverbindungen machen. Am saubersten ist ein komplettes 
herunterfahren und Neuafsetzen des Interfaces in Software.

DHCP Server werden sich in der Regel nicht dran stören, wenn ein Client 
eine neue MAC Adresse dynamisch bekommt; der Client wird dann aber einen 
neuen DHCP request absetzen müssen und im Zweifelsfall eine neue IP 
Adresse bekommen. Hast Du allerdings eine statische IP Adresse, dann 
werden alle Maschinen, die offene Verbindungen mit deinem Gerät hatten, 
nicht mehr damit kommunizieren können, bis der Entry im ARP cache 
geflusht und ein neuer ARP request abgesetzt wurde. Wie lange das 
dauert, hängt von der Konfiguration der Maschinen ab. Können gut 24 
Stunden sein, in denen ARP Einträge vorgehalten werden.

Ausserdem gibt es viele Router, die Port Monitoring betrieben und den 
Port sofort zumachen, wenn eine andere MAC Adresse dort auftaucht.

: Bearbeitet durch User
von Matthias F. (frank91)


Lesenswert?

Hier das komplette Unterprogramm.
wenn ich dich richtig verstanden habe, habe ich so alles richtig 
gemacht?

"ETH_MACAddressConfig" befindet sich ein wenig verschachtelt in der 
"HAL_ETH_Init".
"netif->hwaddr" kommt nach "HAL_ETH_Init".


Im Endeffekt habe ich den Original Code komplett beibehalten. Lediglich 
in
1
/* USER CODE BEGIN MACADDRESS */
2
  /* USER CODE END MACADDRESS */
habe ich etwas eingefügt.


Wenn ich am PC über die Konsole die Mac Adresse des Controllers auslese, 
erhalte ich dort auch die gewünschte Adresse.
1
/*******************************************************************************
2
                       LL Driver Interface ( LwIP stack --> ETH) 
3
*******************************************************************************/
4
/**
5
 * In this function, the hardware should be initialized.
6
 * Called from ethernetif_init().
7
 *
8
 * @param netif the already initialized lwip network interface structure
9
 *        for this ethernetif
10
 */
11
static void low_level_init(struct netif *netif)
12
{ 
13
  uint32_t regvalue = 0;
14
  HAL_StatusTypeDef hal_eth_init_status;
15
  
16
/* Init ETH */
17
18
   uint8_t MACAddr[6] ;
19
  heth.Instance = ETH;
20
  heth.Init.AutoNegotiation = ETH_AUTONEGOTIATION_DISABLE;
21
  heth.Init.Speed = ETH_SPEED_100M;
22
  heth.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
23
  heth.Init.PhyAddress = DP83848_PHY_ADDRESS;
24
  MACAddr[0] = 0x00;
25
  MACAddr[1] = 0x80;
26
  MACAddr[2] = 0xE1;
27
  MACAddr[3] = 0x00;
28
  MACAddr[4] = 0x00;
29
  MACAddr[5] = 0x00;
30
  heth.Init.MACAddr = &MACAddr[0];
31
  heth.Init.RxMode = ETH_RXPOLLING_MODE;
32
  heth.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;
33
  heth.Init.MediaInterface = ETH_MEDIA_INTERFACE_MII;
34
35
  /* USER CODE BEGIN MACADDRESS */
36
  MACAddr[0] = EEPROM_Daten.macAdresse[0];
37
  MACAddr[1] = EEPROM_Daten.macAdresse[1];
38
  MACAddr[2] = EEPROM_Daten.macAdresse[2];
39
  MACAddr[3] = EEPROM_Daten.macAdresse[3];
40
  MACAddr[4] = EEPROM_Daten.macAdresse[4];
41
  MACAddr[5] = EEPROM_Daten.macAdresse[5];
42
  /* USER CODE END MACADDRESS */
43
44
  hal_eth_init_status = HAL_ETH_Init(&heth);
45
46
  if (hal_eth_init_status == HAL_OK)
47
  {
48
    /* Set netif link flag */  
49
    netif->flags |= NETIF_FLAG_LINK_UP;
50
  }
51
  /* Initialize Tx Descriptors list: Chain Mode */
52
  HAL_ETH_DMATxDescListInit(&heth, DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB);
53
     
54
  /* Initialize Rx Descriptors list: Chain Mode  */
55
  HAL_ETH_DMARxDescListInit(&heth, DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB);
56
 
57
#if LWIP_ARP || LWIP_ETHERNET 
58
59
  /* set MAC hardware address length */
60
  netif->hwaddr_len = ETH_HWADDR_LEN;
61
  
62
  /* set MAC hardware address */
63
  netif->hwaddr[0] =  heth.Init.MACAddr[0];
64
  netif->hwaddr[1] =  heth.Init.MACAddr[1];
65
  netif->hwaddr[2] =  heth.Init.MACAddr[2];
66
  netif->hwaddr[3] =  heth.Init.MACAddr[3];
67
  netif->hwaddr[4] =  heth.Init.MACAddr[4];
68
  netif->hwaddr[5] =  heth.Init.MACAddr[5];
69
  
70
  /* maximum transfer unit */
71
  netif->mtu = 1500;
72
  
73
  /* Accept broadcast address and ARP traffic */
74
  /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
75
  #if LWIP_ARP
76
    netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
77
  #else 
78
    netif->flags |= NETIF_FLAG_BROADCAST;
79
  #endif /* LWIP_ARP */
80
  
81
  /* Enable MAC and DMA transmission and reception */
82
  HAL_ETH_Start(&heth);
83
84
/* USER CODE BEGIN PHY_PRE_CONFIG */ 
85
    
86
/* USER CODE END PHY_PRE_CONFIG */
87
  
88
  /**** Configure PHY to generate an interrupt when Eth Link state changes ****/
89
  /* Read Register Configuration */
90
  HAL_ETH_ReadPHYRegister(&heth, PHY_MICR, &regvalue);
91
  
92
  regvalue |= (PHY_MICR_INT_EN | PHY_MICR_INT_OE);
93
94
  /* Enable Interrupts */
95
  HAL_ETH_WritePHYRegister(&heth, PHY_MICR, regvalue );
96
  
97
  /* Read Register Configuration */
98
  HAL_ETH_ReadPHYRegister(&heth, PHY_MISR, &regvalue);
99
  
100
  regvalue |= PHY_MISR_LINK_INT_EN;
101
    
102
  /* Enable Interrupt on change of link status */
103
  HAL_ETH_WritePHYRegister(&heth, PHY_MISR, regvalue);
104
105
/* USER CODE BEGIN PHY_POST_CONFIG */ 
106
    
107
/* USER CODE END PHY_POST_CONFIG */
108
109
#endif /* LWIP_ARP || LWIP_ETHERNET */
110
111
/* USER CODE BEGIN LOW_LEVEL_INIT */ 
112
    
113
/* USER CODE END LOW_LEVEL_INIT */
114
}

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.