/*
- * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
+ * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include "unaligned.h"
const struct in6_addr in6addr_exact = IN6ADDR_EXACT_INIT;
+const struct in6_addr in6addr_all_hosts = IN6ADDR_ALL_HOSTS_INIT;
/* Parses 's' as a 16-digit hexadecimal number representing a datapath ID. On
* success stores the dpid into '*dpidp' and returns true, on failure stores 0
/* Removes outermost VLAN header (if any is present) from 'packet'.
*
- * 'packet->l2_5' should initially point to 'packet''s outer-most MPLS header
- * or may be NULL if there are no MPLS headers. */
+ * 'packet->l2_5' should initially point to 'packet''s outer-most VLAN header
+ * or may be NULL if there are no VLAN headers. */
void
eth_pop_vlan(struct dp_packet *packet)
{
struct vlan_eth_header *veh = dp_packet_l2(packet);
if (veh && dp_packet_size(packet) >= sizeof *veh
- && veh->veth_type == htons(ETH_TYPE_VLAN)) {
+ && eth_type_vlan(veh->veth_type)) {
memmove((char *)veh + VLAN_HEADER_LEN, veh, 2 * ETH_ADDR_LEN);
dp_packet_resize_l2(packet, -VLAN_HEADER_LEN);
return;
}
- if (eh->eth_type == htons(ETH_TYPE_VLAN)) {
+ if (eth_type_vlan(eh->eth_type)) {
ovs_be16 *p;
char *l2_5 = dp_packet_l2_5(packet);
string->length += strlen(dst);
}
+void
+print_ipv6_mapped(struct ds *s, const struct in6_addr *addr)
+{
+ if (IN6_IS_ADDR_V4MAPPED(addr)) {
+ ds_put_format(s, IP_FMT, addr->s6_addr[12], addr->s6_addr[13],
+ addr->s6_addr[14], addr->s6_addr[15]);
+ } else {
+ print_ipv6_addr(s, addr);
+ }
+}
+
void
print_ipv6_masked(struct ds *s, const struct in6_addr *addr,
const struct in6_addr *mask)
#define ARP_PACKET_SIZE (2 + ETH_HEADER_LEN + VLAN_HEADER_LEN + \
ARP_ETH_HEADER_LEN)
+/* Clears 'b' and replaces its contents by an ARP frame with the specified
+ * 'arp_op', 'arp_sha', 'arp_tha', 'arp_spa', and 'arp_tpa'. The outer
+ * Ethernet frame is initialized with Ethernet source 'arp_sha' and destination
+ * 'arp_tha', except that destination ff:ff:ff:ff:ff:ff is used instead if
+ * 'broadcast' is true. */
void
-compose_arp(struct dp_packet *b, const uint8_t eth_src[ETH_ADDR_LEN],
- ovs_be32 ip_src, ovs_be32 ip_dst)
+compose_arp(struct dp_packet *b, uint16_t arp_op,
+ const uint8_t arp_sha[ETH_ADDR_LEN],
+ const uint8_t arp_tha[ETH_ADDR_LEN], bool broadcast,
+ ovs_be32 arp_spa, ovs_be32 arp_tpa)
{
struct eth_header *eth;
struct arp_eth_header *arp;
dp_packet_reserve(b, 2 + VLAN_HEADER_LEN);
eth = dp_packet_put_uninit(b, sizeof *eth);
- memcpy(eth->eth_dst, eth_addr_broadcast, ETH_ADDR_LEN);
- memcpy(eth->eth_src, eth_src, ETH_ADDR_LEN);
+ memcpy(eth->eth_dst, broadcast ? eth_addr_broadcast : arp_tha,
+ ETH_ADDR_LEN);
+ memcpy(eth->eth_src, arp_sha, ETH_ADDR_LEN);
eth->eth_type = htons(ETH_TYPE_ARP);
arp = dp_packet_put_uninit(b, sizeof *arp);
arp->ar_pro = htons(ARP_PRO_IP);
arp->ar_hln = sizeof arp->ar_sha;
arp->ar_pln = sizeof arp->ar_spa;
- arp->ar_op = htons(ARP_OP_REQUEST);
- memcpy(arp->ar_sha, eth_src, ETH_ADDR_LEN);
- memset(arp->ar_tha, 0, ETH_ADDR_LEN);
+ arp->ar_op = htons(arp_op);
+ memcpy(arp->ar_sha, arp_sha, ETH_ADDR_LEN);
+ memcpy(arp->ar_tha, arp_tha, ETH_ADDR_LEN);
- put_16aligned_be32(&arp->ar_spa, ip_src);
- put_16aligned_be32(&arp->ar_tpa, ip_dst);
+ put_16aligned_be32(&arp->ar_spa, arp_spa);
+ put_16aligned_be32(&arp->ar_tpa, arp_tpa);
dp_packet_reset_offsets(b);
dp_packet_set_l3(b, arp);