From 75a4ead16d571a4e30cb4b54c5456e30a20c3d78 Mon Sep 17 00:00:00 2001 From: Ethan Jackson Date: Thu, 3 Nov 2011 13:03:16 -0700 Subject: [PATCH] cfm: Support tagged CCM PDUs. This patch also causes eth_compose() to set the l2 and l3 pointers of the packets which it modifies. --- lib/cfm.c | 11 +++++++++-- lib/cfm.h | 1 + lib/packets.c | 6 +++++- vswitchd/bridge.c | 2 ++ vswitchd/vswitch.xml | 7 +++++++ 5 files changed, 24 insertions(+), 3 deletions(-) diff --git a/lib/cfm.c b/lib/cfm.c index 0d79beed..8acbd093 100644 --- a/lib/cfm.c +++ b/lib/cfm.c @@ -93,6 +93,7 @@ struct cfm { uint32_t seq; /* The sequence number of our last CCM. */ uint8_t ccm_interval; /* The CCM transmission interval. */ int ccm_interval_ms; /* 'ccm_interval' in milliseconds. */ + uint16_t ccm_vlan; /* Vlan tag of CCM PDUs. */ uint8_t maid[CCM_MAID_LEN]; /* The MAID of this CFM. */ struct timer tx_timer; /* Send CCM when expired. */ @@ -345,8 +346,13 @@ cfm_compose_ccm(struct cfm *cfm, struct ofpbuf *packet, struct ccm *ccm; timer_set_duration(&cfm->tx_timer, cfm->ccm_interval_ms); - ccm = eth_compose(packet, cfm_ccm_addr(cfm), eth_src, ETH_TYPE_CFM, - sizeof *ccm); + eth_compose(packet, cfm_ccm_addr(cfm), eth_src, ETH_TYPE_CFM, sizeof *ccm); + + if (cfm->ccm_vlan) { + eth_push_vlan(packet, htons(cfm->ccm_vlan)); + } + + ccm = packet->l3; ccm->mdlevel_version = 0; ccm->opcode = CCM_OPCODE; ccm->tlv_offset = 70; @@ -400,6 +406,7 @@ cfm_configure(struct cfm *cfm, const struct cfm_settings *s) interval = ms_to_ccm_interval(s->interval); interval_ms = ccm_interval_to_ms(interval); + cfm->ccm_vlan = s->ccm_vlan & VLAN_VID_MASK; if (cfm->extended && interval_ms != s->interval) { interval = 0; interval_ms = MIN(s->interval, UINT16_MAX); diff --git a/lib/cfm.h b/lib/cfm.h index 1c46ffa8..334b80c0 100644 --- a/lib/cfm.h +++ b/lib/cfm.h @@ -29,6 +29,7 @@ struct cfm_settings { int interval; /* The requested transmission interval. */ bool extended; /* Run in extended mode. */ bool opup; /* Operational State. */ + uint16_t ccm_vlan; /* CCM Vlan tag. Zero if none. */ }; void cfm_init(void); diff --git a/lib/packets.c b/lib/packets.c index b704276c..03f92e36 100644 --- a/lib/packets.c +++ b/lib/packets.c @@ -259,7 +259,8 @@ ipv6_is_cidr(const struct in6_addr *netmask) /* Populates 'b' with an Ethernet II packet headed with the given 'eth_dst', * 'eth_src' and 'eth_type' parameters. A payload of 'size' bytes is allocated * in 'b' and returned. This payload may be populated with appropriate - * information by the caller. + * information by the caller. Sets 'b''s 'l2' and 'l3' pointers to the + * Ethernet header and payload respectively. * * The returned packet has enough headroom to insert an 802.1Q VLAN header if * desired. */ @@ -282,6 +283,9 @@ eth_compose(struct ofpbuf *b, const uint8_t eth_dst[ETH_ADDR_LEN], memcpy(eth->eth_src, eth_src, ETH_ADDR_LEN); eth->eth_type = htons(eth_type); + b->l2 = eth; + b->l3 = data; + return data; } diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index 09696d5a..5100b787 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -3005,6 +3005,8 @@ iface_configure_cfm(struct iface *iface) s.mpid = *cfg->cfm_mpid; s.interval = atoi(get_interface_other_config(iface->cfg, "cfm_interval", "0")); + s.ccm_vlan = atoi(get_interface_other_config(iface->cfg, "cfm_ccm_vlan", + "0")); if (s.interval <= 0) { s.interval = 1000; } diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml index bcb6b6fd..80d9cdcc 100644 --- a/vswitchd/vswitch.xml +++ b/vswitchd/vswitch.xml @@ -1642,6 +1642,13 @@ OpenFlow action. This setting is ignored when CFM is not in extended mode. Defaults to up. + + + When set, the CFM module will apply a VLAN tag to all CCMs it generates + with the given value. + + -- 2.30.2