On Fri, Nov 14, 2014 at 07:42:07AM -0500, drfl...@avaya.com wrote: > From: Dennis Flynn <drfl...@avaya.com> > > This commit provides the initial delivery of support for the Auto-Attach > standard to Open vSwitch. This standard describes a compact method of using > IEEE 802.1AB Link Layer Discovery Protocol (LLDP) with a IEEE 802.1aq Shortest > Path Bridging (SPB) network to automatically attach network devices not > supporting IEEE 802.1ah to individual services in a SPB network. Specifically > this commit adds base LLDP support to OVS along with the LLDP extension > required to support Auto-Attach. > > The base LLDP code within this commit is adapted from the open source LLDPD > project headed by Vincent Bernat. This base code is augmented with OVS > specific > logic which integrates LLDP into OVS and which extends LLDP to support > Auto-Attach. The required build system changes are provided to include this > new > Auto-Attach feature. > > This is the first of a series of commits. Subsequent commits will be provided > to complete the task of adding Auto-Attach to OVS. > > Signed-off-by: Ludovic Beliveau <ludovic.beliv...@windriver.com> > Signed-off-by: Dennis Flynn <drfl...@avaya.com>
Sorry for the long delay in review. lldp.c and lldpd.c provoke a lot of warnings from "sparse": ../lib/lldp/lldpd.c:79:12: warning: Using plain integer as NULL pointer ../lib/lldp/lldpd.c:214:39: warning: Using plain integer as NULL pointer ../lib/lldp/lldpd.c:214:59: warning: Using plain integer as NULL pointer ../lib/lldp/lldpd.c:214:80: warning: Using plain integer as NULL pointer ../lib/lldp/lldp.c:183:11: warning: incorrect type in assignment (different base types) ../lib/lldp/lldp.c:183:11: expected unsigned short static [unsigned] [toplevel] [usertype] f_uint16 ../lib/lldp/lldp.c:183:11: got restricted ovs_be16 ../lib/lldp/lldp.c:186:11: warning: invalid assignment: |= ../lib/lldp/lldp.c:186:11: left side has type unsigned short ../lib/lldp/lldp.c:186:11: right side has type restricted ovs_be16 ../lib/lldp/lldp.c:191:11: warning: incorrect type in assignment (different base types) ../lib/lldp/lldp.c:191:11: expected unsigned short static [unsigned] [toplevel] [assigned] [usertype] f_uint16 ../lib/lldp/lldp.c:191:11: got restricted ovs_be16 ../lib/lldp/lldp.c:194:11: warning: invalid assignment: |= ../lib/lldp/lldp.c:194:11: left side has type unsigned short ../lib/lldp/lldp.c:194:11: right side has type restricted ovs_be16 ../lib/lldp/lldp.c:199:11: warning: incorrect type in assignment (different base types) ../lib/lldp/lldp.c:199:11: expected unsigned short static [unsigned] [toplevel] [assigned] [usertype] f_uint16 ../lib/lldp/lldp.c:199:11: got restricted ovs_be16 ../lib/lldp/lldp.c:200:11: warning: incorrect type in assignment (different base types) ../lib/lldp/lldp.c:200:11: expected unsigned short static [unsigned] [toplevel] [assigned] [usertype] f_uint16 ../lib/lldp/lldp.c:200:11: got restricted ovs_be16 ../lib/lldp/lldp.c:201:11: warning: invalid assignment: |= ../lib/lldp/lldp.c:201:11: left side has type unsigned short ../lib/lldp/lldp.c:201:11: right side has type restricted ovs_be16 ../lib/lldp/lldp.c:207:15: warning: incorrect type in assignment (different base types) ../lib/lldp/lldp.c:207:15: expected unsigned short static [unsigned] [toplevel] [assigned] [usertype] f_uint16 ../lib/lldp/lldp.c:207:15: got restricted ovs_be16 ../lib/lldp/lldp.c:209:15: warning: invalid assignment: |= ../lib/lldp/lldp.c:209:15: left side has type unsigned short ../lib/lldp/lldp.c:209:15: right side has type restricted ovs_be16 ../lib/lldp/lldp.c:216:15: warning: incorrect type in assignment (different base types) ../lib/lldp/lldp.c:216:15: expected unsigned short static [unsigned] [toplevel] [assigned] [usertype] f_uint16 ../lib/lldp/lldp.c:216:15: got restricted ovs_be16 ../lib/lldp/lldp.c:218:15: warning: invalid assignment: |= ../lib/lldp/lldp.c:218:15: left side has type unsigned short ../lib/lldp/lldp.c:218:15: right side has type restricted ovs_be16 ../lib/lldp/lldp.c:224:11: warning: incorrect type in assignment (different base types) ../lib/lldp/lldp.c:224:11: expected unsigned short static [unsigned] [toplevel] [assigned] [usertype] f_uint16 ../lib/lldp/lldp.c:224:11: got restricted ovs_be16 ../lib/lldp/lldp.c:225:11: warning: incorrect type in assignment (different base types) ../lib/lldp/lldp.c:225:11: expected unsigned short static [unsigned] [toplevel] [assigned] [usertype] f_uint16 ../lib/lldp/lldp.c:225:11: got restricted ovs_be16 ../lib/lldp/lldp.c:226:11: warning: incorrect type in assignment (different base types) ../lib/lldp/lldp.c:226:11: expected unsigned short static [unsigned] [toplevel] [assigned] [usertype] f_uint16 ../lib/lldp/lldp.c:226:11: got restricted ovs_be16 ../lib/lldp/lldp.c:227:11: warning: invalid assignment: |= ../lib/lldp/lldp.c:227:11: left side has type unsigned short ../lib/lldp/lldp.c:227:11: right side has type restricted ovs_be16 ../lib/lldp/lldp.c:237:15: warning: incorrect type in assignment (different base types) ../lib/lldp/lldp.c:237:15: expected unsigned short static [unsigned] [toplevel] [assigned] [usertype] f_uint16 ../lib/lldp/lldp.c:237:15: got restricted ovs_be16 ../lib/lldp/lldp.c:249:19: warning: incorrect type in assignment (different base types) ../lib/lldp/lldp.c:249:19: expected unsigned int static [unsigned] [toplevel] [assigned] [usertype] f_uint32 ../lib/lldp/lldp.c:249:19: got restricted ovs_be32 ../lib/lldp/lldp.c:255:19: warning: incorrect type in assignment (different base types) ../lib/lldp/lldp.c:255:19: expected unsigned int static [unsigned] [toplevel] [assigned] [usertype] f_uint32 ../lib/lldp/lldp.c:255:19: got restricted ovs_be32 ../lib/lldp/lldp.c:261:15: warning: invalid assignment: |= ../lib/lldp/lldp.c:261:15: left side has type unsigned short ../lib/lldp/lldp.c:261:15: right side has type restricted ovs_be16 ../lib/lldp/lldp.c:269:15: warning: incorrect type in assignment (different base types) ../lib/lldp/lldp.c:269:15: expected unsigned short static [unsigned] [toplevel] [assigned] [usertype] f_uint16 ../lib/lldp/lldp.c:269:15: got restricted ovs_be16 ../lib/lldp/lldp.c:271:15: warning: invalid assignment: |= ../lib/lldp/lldp.c:271:15: left side has type unsigned short ../lib/lldp/lldp.c:271:15: right side has type restricted ovs_be16 ../lib/lldp/lldp.c:299:15: warning: incorrect type in assignment (different base types) ../lib/lldp/lldp.c:299:15: expected unsigned short static [unsigned] [toplevel] [assigned] [usertype] f_uint16 ../lib/lldp/lldp.c:299:15: got restricted ovs_be16 ../lib/lldp/lldp.c:310:15: warning: invalid assignment: |= ../lib/lldp/lldp.c:310:15: left side has type unsigned short ../lib/lldp/lldp.c:310:15: right side has type restricted ovs_be16 ../lib/lldp/lldp.c:320:15: warning: incorrect type in assignment (different base types) ../lib/lldp/lldp.c:320:15: expected unsigned short static [unsigned] [toplevel] [assigned] [usertype] f_uint16 ../lib/lldp/lldp.c:320:15: got restricted ovs_be16 ../lib/lldp/lldp.c:337:23: warning: incorrect type in assignment (different base types) ../lib/lldp/lldp.c:337:23: expected unsigned short static [unsigned] [toplevel] [assigned] [usertype] f_uint16 ../lib/lldp/lldp.c:337:23: got restricted ovs_be16 ../lib/lldp/lldp.c:347:15: warning: invalid assignment: |= ../lib/lldp/lldp.c:347:15: left side has type unsigned short ../lib/lldp/lldp.c:347:15: right side has type restricted ovs_be16 ../lib/lldp/lldp.c:353:11: warning: incorrect type in assignment (different base types) ../lib/lldp/lldp.c:353:11: expected unsigned short static [unsigned] [toplevel] [assigned] [usertype] f_uint16 ../lib/lldp/lldp.c:353:11: got restricted ovs_be16 ../lib/lldp/lldp.c:354:11: warning: invalid assignment: |= ../lib/lldp/lldp.c:354:11: left side has type unsigned short ../lib/lldp/lldp.c:354:11: right side has type restricted ovs_be16 ../lib/lldp/lldp.c:449:9: warning: incorrect type in argument 1 (different base types) ../lib/lldp/lldp.c:449:9: expected restricted ovs_be16 [usertype] x ../lib/lldp/lldp.c:449:9: got unsigned short static [unsigned] [toplevel] [assigned] [usertype] f_uint16 ../lib/lldp/lldp.c:460:20: warning: incorrect type in argument 1 (different base types) ../lib/lldp/lldp.c:460:20: expected restricted ovs_be16 [usertype] x ../lib/lldp/lldp.c:460:20: got unsigned short static [unsigned] [toplevel] [assigned] [usertype] f_uint16 ../lib/lldp/lldp.c:508:30: warning: incorrect type in argument 1 (different base types) ../lib/lldp/lldp.c:508:30: expected restricted ovs_be16 [usertype] x ../lib/lldp/lldp.c:508:30: got unsigned short static [unsigned] [toplevel] [assigned] [usertype] f_uint16 ../lib/lldp/lldp.c:535:40: warning: incorrect type in argument 1 (different base types) ../lib/lldp/lldp.c:535:40: expected restricted ovs_be16 [usertype] x ../lib/lldp/lldp.c:535:40: got unsigned short static [unsigned] [toplevel] [assigned] [usertype] f_uint16 ../lib/lldp/lldp.c:536:38: warning: incorrect type in argument 1 (different base types) ../lib/lldp/lldp.c:536:38: expected restricted ovs_be16 [usertype] x ../lib/lldp/lldp.c:536:38: got unsigned short static [unsigned] [toplevel] [assigned] [usertype] f_uint16 ../lib/lldp/lldp.c:548:28: warning: incorrect type in argument 1 (different base types) ../lib/lldp/lldp.c:548:28: expected restricted ovs_be32 [usertype] x ../lib/lldp/lldp.c:548:28: got unsigned int static [unsigned] [toplevel] [assigned] [usertype] f_uint32 ../lib/lldp/lldp.c:585:39: warning: incorrect type in argument 1 (different base types) ../lib/lldp/lldp.c:585:39: expected restricted ovs_be16 [usertype] x ../lib/lldp/lldp.c:585:39: got unsigned short static [unsigned] [toplevel] [assigned] [usertype] f_uint16 ../lib/lldp/lldp.c:602:41: warning: incorrect type in argument 1 (different base types) ../lib/lldp/lldp.c:602:41: expected restricted ovs_be16 [usertype] x ../lib/lldp/lldp.c:602:41: got unsigned short static [unsigned] [toplevel] [assigned] [usertype] f_uint16 ../lib/lldp/lldp.c:630:51: warning: incorrect type in argument 1 (different base types) ../lib/lldp/lldp.c:630:51: expected restricted ovs_be16 [usertype] x ../lib/lldp/lldp.c:630:51: got unsigned short static [unsigned] [toplevel] [assigned] [usertype] f_uint16 CCLD ofproto/libofproto.la ../lib/ovs-lldp.c:837:31: warning: Using plain integer as NULL pointer ovs-lldp.c ---------- ovs-lldp.c includes one lib header using a "lib/" prefix, which is unnecessary: #include "lib/dynamic-string.h" (While you're at it, it's best to put the headers in alphabetical order, see CodingStyle.md.) I see a lot of "static inline" function in ovs-lldp.c; see CodingStyle.md: Functions in .c files should not normally be marked "inline", because it does not usually help code generation and it does suppress compilers warnings about unused functions. (Functions defined in .h usually should be marked inline.) chassisid_to_string() uses malloc() without checking the return value. I suggest using xmalloc() instead. None of its callers seem to free the output string; I think that's a memory leak. I see a number of lines just over OVS's customary 79-character limit. I see many uses of hash_bytes() to hash a pointer. I suggest hash_pointer(). This file is very heavy on casts. Most of them should be removed. Here are a few that illustrate the pattern that I would follow: diff --git a/lib/ovs-lldp.c b/lib/ovs-lldp.c index 4ef607c..0f43342 100644 --- a/lib/ovs-lldp.c +++ b/lib/ovs-lldp.c @@ -225,11 +225,10 @@ aa_print_lldp_and_aa_stats(struct ds *ds, struct lldp *lldp) return; } - hardware_start = ((struct lldpd_hardware *) &lldp->lldpd->g_hardware); - hardware = (struct lldpd_hardware *) ((struct list *) hardware_start)->next; + hardware_start = &lldp->lldpd->g_hardware; + hardware = (struct lldpd_hardware *) hardware_start->h_entries.next; while (hardware && ( hardware != hardware_start)) { - ds_put_format(ds, "\ttx cnt: %llu\n", - (long long unsigned int) hardware->h_tx_cnt); + ds_put_format(ds, "\ttx cnt: %"PRIu64"\n", hardware->h_tx_cnt); ds_put_format(ds, "\trx cnt: %llu\n", (long long unsigned int) hardware->h_rx_cnt); ds_put_format(ds, "\trx discarded cnt: %llu\n", @@ -245,7 +244,7 @@ aa_print_lldp_and_aa_stats(struct ds *ds, struct lldp *lldp) ds_put_format(ds, "\tdrop cnt: %llu\n", (long long unsigned int) hardware->h_drop_cnt); - hardware = (struct lldpd_hardware *) ((struct list *) hardware)->next; + hardware = (struct lldpd_hardware *) hardware->h_entries.next; } } Actually, though I'm not certain what's going on (because of the whole lldpd_hardware instance in struct lldpd, instead of just a "struct list", which would be usual at least in OVS), it looks like the loop in this function is just a long way to write LIST_FOR_EACH, which makes iteration much easier to understand: diff --git a/lib/ovs-lldp.c b/lib/ovs-lldp.c index 4ef607c..437870d 100644 --- a/lib/ovs-lldp.c +++ b/lib/ovs-lldp.c @@ -217,7 +217,7 @@ static void aa_print_lldp_and_aa_stats(struct ds *ds, struct lldp *lldp) OVS_REQUIRES(mutex) { - struct lldpd_hardware *hardware, *hardware_start; + const struct lldpd_hardware *hardware; ds_put_format(ds, "Statistics: %s\n", lldp->name); @@ -225,11 +225,8 @@ aa_print_lldp_and_aa_stats(struct ds *ds, struct lldp *lldp) return; } - hardware_start = ((struct lldpd_hardware *) &lldp->lldpd->g_hardware); - hardware = (struct lldpd_hardware *) ((struct list *) hardware_start)->next; - while (hardware && ( hardware != hardware_start)) { - ds_put_format(ds, "\ttx cnt: %llu\n", - (long long unsigned int) hardware->h_tx_cnt); + LIST_FOR_EACH (hardware, h_entries, &lldp->lldpd->g_hardware.h_entries) { + ds_put_format(ds, "\ttx cnt: %"PRIu64"\n", hardware->h_tx_cnt); ds_put_format(ds, "\trx cnt: %llu\n", (long long unsigned int) hardware->h_rx_cnt); ds_put_format(ds, "\trx discarded cnt: %llu\n", @@ -244,8 +241,6 @@ aa_print_lldp_and_aa_stats(struct ds *ds, struct lldp *lldp) (long long unsigned int) hardware->h_delete_cnt); ds_put_format(ds, "\tdrop cnt: %llu\n", (long long unsigned int) hardware->h_drop_cnt); - - hardware = (struct lldpd_hardware *) ((struct list *) hardware)->next; } } I see tons of these handmade list iterations. Can you switch all of them to LIST_FOR_EACH? In update_mapping_on_lldp(), I would remove the parentheses following sizeof in multiple places, following CodingStyle.md: The "sizeof" operator is unique among C operators in that it accepts two very different kinds of operands: an expression or a type. In general, prefer to specify an expression, e.g. "int *x = xmalloc(sizeof *x);". When the operand of sizeof is an expression, there is no need to parenthesize that operand, and please don't. Here, however, I would use ARRAY_SIZE: sizeof(lm->isid_vlan_data.isid) / sizeof(lm->isid_vlan_data.isid[0]), This code in update_mapping_on_lldp() looks odd. Why isn't the list initialized whenever its containing data structure is allocated? (I didn't track down where that happens to see if there's some good reason.) if (hardware->h_lport.p_isid_vlan_maps.m_entries.next == NULL && hardware->h_lport.p_isid_vlan_maps.m_entries.prev == NULL) { list_init((struct list *) &hardware->h_lport.p_isid_vlan_maps); } The aa_get_vlan_queued() interface looks odd; why doesn't it take a "struct list *"? It seems strange to xmalloc() just a single struct list on the caller's behalf. In aa_configure(), I suggest just looking at whether s->system_description[0] is nonzero instead of calling strlen(). It looks like there are two copies of every aa_mapping_internal just so that they can be in two hmaps. That's not necessary; you can just add two hmap_nodes to aa_mapping_internal and then add them to separate hmaps. I don't think the memsets in lldp_init() are needed--aren't these static variables, that will automatically be initialized by the loader? I don't see why lldp_should_process_flow() modifies wc->masks.dl_dst, since it doesn't examine it. If anything, I'd expect it to modify wc->masks.dl_type, since it does examine that, but that's unnecessary since dl_type is always unwildcarded at a higher level. In lldp_should_process_flow(), please write this: return (ntohs(flow->dl_type) == ETH_TYPE_LLDP); as: return flow->dl_type == htons(ETH_TYPE_LLDP); because the compiler can optimize it better. Here, please put "void" on a line of its own: void lldp_put_packet(struct lldp *lldp, struct ofpbuf *packet, uint8_t eth_src[ETH_ADDR_LEN]) lldp_put_packet() should use xmalloc() instead of malloc(), but actually I don't see why it's allocating memory directly at all. The ofpbuf API should be sufficient; please use it instead of creating a separate buffer on the side and then copying in. I see another bare malloc() in lldp_create(). In lldp_create(), when lldpd_alloc_hardware() fails, I think I would just call out_of_memory(). Why is there a special case for IFF_RUNNING on Windows? In lldp_create() here, why not use xstrdup()? And the p_id is obviously always created from a null-terminated string; why is it copied into a length-based string? hardware->h_lport.p_id = malloc(strlen(netdev_get_name(netdev))); hardware->h_lport.p_id_len = strlen(netdev_get_name(netdev)); memcpy(hardware->h_lport.p_id, netdev_get_name(netdev), strlen(netdev_get_name(netdev))); This code here: p = xzalloc(sizeof *p); memcpy(p, m, sizeof *p); can be written more simply as: p = xmemdup(m, sizeof *p); although again I think we can avoid having two copies. Not sure of safety in lldp_unref(). Is it possible for a client to get a reference to 'lldp', via 'all_llldps', between the final unref and the hmap removal? _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev