ip link add link <master> name <slave> type ipvlan [ mode MODE ] [ FLAGS ]
where
MODE: l3 (default) | l3s | l2
- FLAGS: bridge (default) | private
+ FLAGS: bridge (default) | private | vepa
e.g.
(a) Following will create IPvlan link with eth0 as master in
bash# ip link add link eth0 name ipvl0 type ipvlan mode l2 bridge
(c) This command will create an IPvlan device in L2 private mode.
bash# ip link add link eth0 name ipvlan type ipvlan mode l2 private
+ (d) This command will create an IPvlan device in L2 vepa mode.
+ bash# ip link add link eth0 name ipvlan type ipvlan mode l2 vepa
4. Operating modes:
If this option is added to the command-line, the port is set in private
mode. i.e. port wont allow cross communication between slaves.
+5.3 vepa:
+ If this is added to the command-line, the port is set in VEPA mode.
+i.e. port will offload switching functionality to the external entity as
+described in 802.1Qbg
+Note: VEPA mode in IPvlan has limitations. IPvlan uses the mac-address of the
+master-device, so the packets which are emitted in this mode for the adjacent
+neighbor will have source and destination mac same. This will make the switch /
+router send the redirect message.
6. What to choose (macvlan vs. ipvlan)?
These two devices are very similar in many regards and the specific use
port->flags &= ~IPVLAN_F_PRIVATE;
}
+static inline bool ipvlan_is_vepa(const struct ipvl_port *port)
+{
+ return !!(port->flags & IPVLAN_F_VEPA);
+}
+
+static inline void ipvlan_mark_vepa(struct ipvl_port *port)
+{
+ port->flags |= IPVLAN_F_VEPA;
+}
+
+static inline void ipvlan_clear_vepa(struct ipvl_port *port)
+{
+ port->flags &= ~IPVLAN_F_VEPA;
+}
+
void ipvlan_init_secret(void);
unsigned int ipvlan_mac_hash(const unsigned char *addr);
rx_handler_result_t ipvlan_handle_frame(struct sk_buff **pskb);
if (!lyr3h)
goto out;
- addr = ipvlan_addr_lookup(ipvlan->port, lyr3h, addr_type, true);
- if (addr) {
- if (ipvlan_is_private(ipvlan->port)) {
- consume_skb(skb);
- return NET_XMIT_DROP;
+ if (!ipvlan_is_vepa(ipvlan->port)) {
+ addr = ipvlan_addr_lookup(ipvlan->port, lyr3h, addr_type, true);
+ if (addr) {
+ if (ipvlan_is_private(ipvlan->port)) {
+ consume_skb(skb);
+ return NET_XMIT_DROP;
+ }
+ return ipvlan_rcv_frame(addr, &skb, true);
}
- return ipvlan_rcv_frame(addr, &skb, true);
}
out:
ipvlan_skb_crossing_ns(skb, ipvlan->phy_dev);
void *lyr3h;
int addr_type;
- if (ether_addr_equal(eth->h_dest, eth->h_source)) {
+ if (!ipvlan_is_vepa(ipvlan->port) &&
+ ether_addr_equal(eth->h_dest, eth->h_source)) {
lyr3h = ipvlan_get_L3_hdr(skb, &addr_type);
if (lyr3h) {
addr = ipvlan_addr_lookup(ipvlan->port, lyr3h, addr_type, true);
ipvlan_mark_private(port);
else
ipvlan_clear_private(port);
+
+ if (flags & IPVLAN_F_VEPA)
+ ipvlan_mark_vepa(port);
+ else
+ ipvlan_clear_vepa(port);
}
return err;
if (data[IFLA_IPVLAN_FLAGS]) {
u16 flags = nla_get_u16(data[IFLA_IPVLAN_FLAGS]);
- /* Only one bit is used at this moment. */
- if (flags & ~IPVLAN_F_PRIVATE)
+ /* Only two bits are used at this moment. */
+ if (flags & ~(IPVLAN_F_PRIVATE | IPVLAN_F_VEPA))
+ return -EINVAL;
+ /* Also both flags can't be active at the same time. */
+ if ((flags & (IPVLAN_F_PRIVATE | IPVLAN_F_VEPA)) ==
+ (IPVLAN_F_PRIVATE | IPVLAN_F_VEPA))
return -EINVAL;
}
};
#define IPVLAN_F_PRIVATE 0x01
+#define IPVLAN_F_VEPA 0x02
/* VXLAN section */
enum {