Finishing documentation
diff --git a/openstack/networking/v2/networks/doc.go b/openstack/networking/v2/networks/doc.go
index 83c4a6a..c87a7ce 100644
--- a/openstack/networking/v2/networks/doc.go
+++ b/openstack/networking/v2/networks/doc.go
@@ -1 +1,9 @@
+// Package networks contains functionality for working with Neutron network
+// resources. A network is an isolated virtual layer-2 broadcast domain that is
+// typically reserved for the tenant who created it (unless you configure the
+// network to be shared). Tenants can create multiple networks until the
+// thresholds per-tenant quota is reached.
+//
+// In the v2.0 Networking API, the network is the main entity. Ports and subnets
+// are always associated with a network.
 package networks
diff --git a/openstack/networking/v2/networks/errors.go b/openstack/networking/v2/networks/errors.go
index 7a67ef7..83c4a6a 100644
--- a/openstack/networking/v2/networks/errors.go
+++ b/openstack/networking/v2/networks/errors.go
@@ -1,16 +1 @@
 package networks
-
-import "fmt"
-
-func requiredAttr(attr string) error {
-	return fmt.Errorf("You must specify %s for this resource", attr)
-}
-
-func err(str string) error {
-	return fmt.Errorf("%s", str)
-}
-
-var (
-	ErrNameRequired = requiredAttr("name")
-	ErrNoURLFound   = err("Next URL could not be extracted from collection")
-)
diff --git a/openstack/networking/v2/networks/requests.go b/openstack/networking/v2/networks/requests.go
index 4f1037e..f4fbe97 100644
--- a/openstack/networking/v2/networks/requests.go
+++ b/openstack/networking/v2/networks/requests.go
@@ -9,20 +9,6 @@
 	"github.com/rackspace/gophercloud/pagination"
 )
 
-type ListOpts struct {
-	Status       string
-	Name         string
-	AdminStateUp *bool
-	TenantID     string
-	Shared       *bool
-	ID           string
-	Page         int
-	PerPage      int
-	Limit        int
-	SortKey      string
-	SortDir      string
-}
-
 type networkOpts struct {
 	AdminStateUp bool
 	Name         string
@@ -40,6 +26,27 @@
 	}
 }
 
+// ListOpts allows the filtering and sorting of paginated collections through
+// the API. Filtering is achieved by passing in struct field values that map to
+// the network attributes you want to see returned. SortKey allows you to sort
+// by a particular network attribute. SortDir sets the direction, and is either
+// `asc' or `desc'. Marker and Limit are used for pagination.
+type ListOpts struct {
+	Status       string
+	Name         string
+	AdminStateUp *bool
+	TenantID     string
+	Shared       *bool
+	ID           string
+	Marker       string
+	Limit        int
+	SortKey      string
+	SortDir      string
+}
+
+// List returns a Pager which allows you to iterate over a collection of
+// networks. It accepts a ListOpts struct, which allows you to filter and sort
+// the returned collection for greater efficiency.
 func List(c *gophercloud.ServiceClient, opts ListOpts) pagination.Pager {
 	// Build query parameters
 	q := make(map[string]string)
@@ -61,11 +68,8 @@
 	if opts.ID != "" {
 		q["id"] = opts.ID
 	}
-	if opts.Page != 0 {
-		q["page"] = strconv.Itoa(opts.Page)
-	}
-	if opts.PerPage != 0 {
-		q["per_page"] = strconv.Itoa(opts.PerPage)
+	if opts.Marker != "" {
+		q["marker"] = opts.Marker
 	}
 	if opts.Limit != 0 {
 		q["limit"] = strconv.Itoa(opts.Limit)
@@ -77,15 +81,16 @@
 		q["sort_dir"] = opts.SortDir
 	}
 
-	u := ListURL(c) + utils.BuildQuery(q)
+	u := listURL(c) + utils.BuildQuery(q)
 	return pagination.NewPager(c, u, func(r pagination.LastHTTPResponse) pagination.Page {
 		return NetworkPage{pagination.LinkedPageBase(r)}
 	})
 }
 
+// Get retrieves a specific network based on its unique ID.
 func Get(c *gophercloud.ServiceClient, id string) (*Network, error) {
 	var n Network
-	_, err := perigee.Request("GET", GetURL(c, id), perigee.Options{
+	_, err := perigee.Request("GET", getURL(c, id), perigee.Options{
 		MoreHeaders: c.Provider.AuthenticatedHeaders(),
 		Results: &struct {
 			Network *Network `json:"network"`
@@ -98,13 +103,21 @@
 	return &n, nil
 }
 
+// CreateOpts represents the attributes used when creating a new network.
 type CreateOpts networkOpts
 
+// Create accepts a CreateOpts struct and creates a new network using the values
+// provided. This operation does not actually require a request body, i.e. the
+// CreateOpts struct argument can be empty.
+//
+// The tenant ID that is contained in the URI is the tenant that creates the
+// network. An admin user, however, has the option of specifying another tenant
+// ID in the CreateOpts struct.
 func Create(c *gophercloud.ServiceClient, opts CreateOpts) (*NetworkCreateResult, error) {
 	// Define structures
 	type network struct {
-		AdminStateUp bool    `json:"admin_state_up"`
-		Name         string  `json:"name"`
+		AdminStateUp bool    `json:"admin_state_up,omitempty"`
+		Name         string  `json:"name,omitempty"`
 		Shared       *bool   `json:"shared,omitempty"`
 		TenantID     *string `json:"tenant_id,omitempty"`
 	}
@@ -115,11 +128,6 @@
 		Network *NetworkCreateResult `json:"network"`
 	}
 
-	// Validate
-	if opts.Name == "" {
-		return nil, ErrNameRequired
-	}
-
 	// Populate request body
 	reqBody := request{Network: network{
 		AdminStateUp: opts.AdminStateUp,
@@ -133,7 +141,7 @@
 
 	// Send request to API
 	var res response
-	_, err := perigee.Request("POST", CreateURL(c), perigee.Options{
+	_, err := perigee.Request("POST", createURL(c), perigee.Options{
 		MoreHeaders: c.Provider.AuthenticatedHeaders(),
 		ReqBody:     &reqBody,
 		Results:     &res,
@@ -146,8 +154,11 @@
 	return res.Network, nil
 }
 
+// UpdateOpts represents the attributes used when updating an existing network.
 type UpdateOpts networkOpts
 
+// Update accepts a UpdateOpts struct and updates an existing network using the
+// values provided. For more information, see the Create function.
 func Update(c *gophercloud.ServiceClient, networkID string, opts UpdateOpts) (*Network, error) {
 	// Define structures
 	type network struct {
@@ -172,7 +183,7 @@
 
 	// Send request to API
 	var res response
-	_, err := perigee.Request("PUT", GetURL(c, networkID), perigee.Options{
+	_, err := perigee.Request("PUT", getURL(c, networkID), perigee.Options{
 		MoreHeaders: c.Provider.AuthenticatedHeaders(),
 		ReqBody:     &reqBody,
 		Results:     &res,
@@ -185,8 +196,9 @@
 	return res.Network, nil
 }
 
+// Delete accepts a unique ID and deletes the network associated with it.
 func Delete(c *gophercloud.ServiceClient, networkID string) error {
-	_, err := perigee.Request("DELETE", DeleteURL(c, networkID), perigee.Options{
+	_, err := perigee.Request("DELETE", deleteURL(c, networkID), perigee.Options{
 		MoreHeaders: c.Provider.AuthenticatedHeaders(),
 		OkCodes:     []int{204},
 	})
diff --git a/openstack/networking/v2/networks/results.go b/openstack/networking/v2/networks/results.go
index 78bdff5..7f9e51a 100644
--- a/openstack/networking/v2/networks/results.go
+++ b/openstack/networking/v2/networks/results.go
@@ -5,12 +5,14 @@
 	"github.com/rackspace/gophercloud/pagination"
 )
 
+// NetworkProvider represents provider extension data
 type NetworkProvider struct {
 	ProviderSegmentationID  int    `json:"provider:segmentation_id"`
 	ProviderPhysicalNetwork string `json:"provider:physical_network"`
 	ProviderNetworkType     string `json:"provider:network_type"`
 }
 
+// Network represents, well, a network.
 type Network struct {
 	// UUID for the network
 	ID string `mapstructure:"id" json:"id"`
@@ -34,17 +36,23 @@
 	RouterExternal          bool   `mapstructure:"router:external" json:"router:external"`
 }
 
+// NetworkCreateResult represents what is returned by a create operation.
 type NetworkCreateResult struct {
 	Network
 	Segments            []NetworkProvider `json:"segments"`
 	PortSecurityEnabled bool              `json:"port_security_enabled"`
 }
 
+// NetworkPage is the page returned by a pager when traversing over a
+// collection of networks.
 type NetworkPage struct {
 	pagination.LinkedPageBase
 }
 
-func (current NetworkPage) NextPageURL() (string, error) {
+// NextPageURL is invoked when a paginated collection of networks has reached
+// the end of a page and the pager seeks to traverse over a new one. In order
+// to do this, it needs to construct the next page's URL.
+func (p NetworkPage) NextPageURL() (string, error) {
 	type link struct {
 		Href string `mapstructure:"href"`
 		Rel  string `mapstructure:"rel"`
@@ -54,7 +62,7 @@
 	}
 
 	var r resp
-	err := mapstructure.Decode(current.Body, &r)
+	err := mapstructure.Decode(p.Body, &r)
 	if err != nil {
 		return "", err
 	}
@@ -72,14 +80,18 @@
 	return url, nil
 }
 
-func (r NetworkPage) IsEmpty() (bool, error) {
-	is, err := ExtractNetworks(r)
+// IsEmpty checks whether a NetworkPage struct is empty.
+func (p NetworkPage) IsEmpty() (bool, error) {
+	is, err := ExtractNetworks(p)
 	if err != nil {
 		return true, nil
 	}
 	return len(is) == 0, nil
 }
 
+// ExtractNetworks accepts a Page struct, specifically a NetworkPage struct,
+// and extracts the elements into a slice of Network structs. In other words,
+// a generic collection is mapped into a relevant slice.
 func ExtractNetworks(page pagination.Page) ([]Network, error) {
 	var resp struct {
 		Networks []Network `mapstructure:"networks" json:"networks"`
diff --git a/openstack/networking/v2/networks/urls.go b/openstack/networking/v2/networks/urls.go
index a0d660a..80c307c 100644
--- a/openstack/networking/v2/networks/urls.go
+++ b/openstack/networking/v2/networks/urls.go
@@ -4,26 +4,26 @@
 
 const Version = "v2.0"
 
-func ResourceURL(c *gophercloud.ServiceClient, id string) string {
+func resourceURL(c *gophercloud.ServiceClient, id string) string {
 	return c.ServiceURL(Version, "networks", id)
 }
 
-func RootURL(c *gophercloud.ServiceClient) string {
+func rootURL(c *gophercloud.ServiceClient) string {
 	return c.ServiceURL(Version, "networks")
 }
 
-func GetURL(c *gophercloud.ServiceClient, id string) string {
-	return ResourceURL(c, id)
+func getURL(c *gophercloud.ServiceClient, id string) string {
+	return resourceURL(c, id)
 }
 
-func ListURL(c *gophercloud.ServiceClient) string {
-	return RootURL(c)
+func listURL(c *gophercloud.ServiceClient) string {
+	return rootURL(c)
 }
 
-func CreateURL(c *gophercloud.ServiceClient) string {
-	return RootURL(c)
+func createURL(c *gophercloud.ServiceClient) string {
+	return rootURL(c)
 }
 
-func DeleteURL(c *gophercloud.ServiceClient, id string) string {
-	return ResourceURL(c, id)
+func deleteURL(c *gophercloud.ServiceClient, id string) string {
+	return resourceURL(c, id)
 }
diff --git a/openstack/networking/v2/networks/urls_test.go b/openstack/networking/v2/networks/urls_test.go
index 84a7ae6..713a547 100644
--- a/openstack/networking/v2/networks/urls_test.go
+++ b/openstack/networking/v2/networks/urls_test.go
@@ -7,32 +7,32 @@
 	th "github.com/rackspace/gophercloud/testhelper"
 )
 
-const Endpoint = "http://localhost:57909/"
+const endpoint = "http://localhost:57909/"
 
-func EndpointClient() *gophercloud.ServiceClient {
-	return &gophercloud.ServiceClient{Endpoint: Endpoint}
+func endpointClient() *gophercloud.ServiceClient {
+	return &gophercloud.ServiceClient{Endpoint: endpoint}
 }
 
 func TestGetURL(t *testing.T) {
-	actual := GetURL(EndpointClient(), "foo")
-	expected := Endpoint + "v2.0/networks/foo"
+	actual := getURL(endpointClient(), "foo")
+	expected := endpoint + "v2.0/networks/foo"
 	th.AssertEquals(t, expected, actual)
 }
 
 func TestCreateURL(t *testing.T) {
-	actual := CreateURL(EndpointClient())
-	expected := Endpoint + "v2.0/networks"
+	actual := createURL(endpointClient())
+	expected := endpoint + "v2.0/networks"
 	th.AssertEquals(t, expected, actual)
 }
 
 func TestListURL(t *testing.T) {
-	actual := CreateURL(EndpointClient())
-	expected := Endpoint + "v2.0/networks"
+	actual := createURL(endpointClient())
+	expected := endpoint + "v2.0/networks"
 	th.AssertEquals(t, expected, actual)
 }
 
 func TestDeleteURL(t *testing.T) {
-	actual := DeleteURL(EndpointClient(), "foo")
-	expected := Endpoint + "v2.0/networks/foo"
+	actual := deleteURL(endpointClient(), "foo")
+	expected := endpoint + "v2.0/networks/foo"
 	th.AssertEquals(t, expected, actual)
 }
diff --git a/openstack/networking/v2/ports/doc.go b/openstack/networking/v2/ports/doc.go
index 808de88..f16a4bb 100644
--- a/openstack/networking/v2/ports/doc.go
+++ b/openstack/networking/v2/ports/doc.go
@@ -1 +1,8 @@
+// Package ports contains functionality for working with Neutron port resources.
+// A port represents a virtual switch port on a logical network switch. Virtual
+// instances attach their interfaces into ports. The logical port also defines
+// the MAC address and the IP address(es) to be assigned to the interfaces
+// plugged into them. When IP addresses are associated to a port, this also
+// implies the port is associated with a subnet, as the IP address was taken
+// from the allocation pool for a specific subnet.
 package ports
diff --git a/openstack/networking/v2/ports/errors.go b/openstack/networking/v2/ports/errors.go
index 55c01e9..111d977 100644
--- a/openstack/networking/v2/ports/errors.go
+++ b/openstack/networking/v2/ports/errors.go
@@ -7,5 +7,5 @@
 }
 
 var (
-	ErrNetworkIDRequired = err("A Network ID is required")
+	errNetworkIDRequired = err("A Network ID is required")
 )
diff --git a/openstack/networking/v2/ports/requests.go b/openstack/networking/v2/ports/requests.go
index cc0949f..78c96ab 100644
--- a/openstack/networking/v2/ports/requests.go
+++ b/openstack/networking/v2/ports/requests.go
@@ -9,6 +9,18 @@
 	"github.com/rackspace/gophercloud/pagination"
 )
 
+func maybeString(original string) *string {
+	if original != "" {
+		return &original
+	}
+	return nil
+}
+
+// ListOpts allows the filtering and sorting of paginated collections through
+// the API. Filtering is achieved by passing in struct field values that map to
+// the port attributes you want to see returned. SortKey allows you to sort
+// by a particular port attribute. SortDir sets the direction, and is either
+// `asc' or `desc'. Marker and Limit are used for pagination.
 type ListOpts struct {
 	Status          string
 	Name            string
@@ -18,18 +30,23 @@
 	DeviceOwner     string
 	MACAddress      string
 	ID              string
-	SecurityGroups  string
 	DeviceID        string
 	BindingHostID   string
 	BindingVIFType  string
 	BindingVNICType string
 	Limit           int
-	Page            string
-	PerPage         string
+	Marker          string
 	SortKey         string
 	SortDir         string
 }
 
+// List returns a Pager which allows you to iterate over a collection of
+// ports. It accepts a ListOpts struct, which allows you to filter and sort
+// the returned collection for greater efficiency.
+//
+// Default policy settings return only those ports that are owned by the tenant
+// who submits the request, unless the request is submitted by an user with
+// administrative rights.
 func List(c *gophercloud.ServiceClient, opts ListOpts) pagination.Pager {
 	// Build query parameters
 	q := make(map[string]string)
@@ -57,9 +74,6 @@
 	if opts.ID != "" {
 		q["id"] = opts.ID
 	}
-	if opts.SecurityGroups != "" {
-		q["security_groups"] = opts.SecurityGroups
-	}
 	if opts.DeviceID != "" {
 		q["device_id"] = opts.DeviceID
 	}
@@ -78,11 +92,8 @@
 	if opts.Limit != 0 {
 		q["limit"] = strconv.Itoa(opts.Limit)
 	}
-	if opts.Page != "" {
-		q["page"] = opts.Page
-	}
-	if opts.PerPage != "" {
-		q["per_page"] = opts.PerPage
+	if opts.Marker != "" {
+		q["marker"] = opts.Marker
 	}
 	if opts.SortKey != "" {
 		q["sort_key"] = opts.SortKey
@@ -97,6 +108,7 @@
 	})
 }
 
+// Get retrieves a specific port based on its unique ID.
 func Get(c *gophercloud.ServiceClient, id string) (*Port, error) {
 	var p Port
 	_, err := perigee.Request("GET", getURL(c, id), perigee.Options{
@@ -112,13 +124,7 @@
 	return &p, nil
 }
 
-func maybeString(original string) *string {
-	if original != "" {
-		return &original
-	}
-	return nil
-}
-
+// CreateOpts represents the attributes used when creating a new port.
 type CreateOpts struct {
 	NetworkID      string
 	Name           string
@@ -131,9 +137,11 @@
 	SecurityGroups []string
 }
 
+// Create accepts a CreateOpts struct and creates a new network using the values
+// provided. You must remember to provide a NetworkID value.
 func Create(c *gophercloud.ServiceClient, opts CreateOpts) (*Port, error) {
 	type port struct {
-		NetworkID      string      `json:"network_id,omitempty"`
+		NetworkID      string      `json:"network_id"`
 		Name           *string     `json:"name,omitempty"`
 		AdminStateUp   *bool       `json:"admin_state_up,omitempty"`
 		MACAddress     *string     `json:"mac_address,omitempty"`
@@ -149,7 +157,7 @@
 
 	// Validate
 	if opts.NetworkID == "" {
-		return nil, ErrNetworkIDRequired
+		return nil, errNetworkIDRequired
 	}
 
 	// Populate request body
@@ -190,6 +198,7 @@
 	return res.Port, nil
 }
 
+// UpdateOpts represents the attributes used when updating an existing port.
 type UpdateOpts struct {
 	Name           string
 	AdminStateUp   *bool
@@ -199,6 +208,8 @@
 	SecurityGroups []string
 }
 
+// Update accepts a UpdateOpts struct and updates an existing port using the
+// values provided.
 func Update(c *gophercloud.ServiceClient, id string, opts UpdateOpts) (*Port, error) {
 	type port struct {
 		Name           *string     `json:"name,omitempty"`
@@ -246,6 +257,7 @@
 	return res.Port, nil
 }
 
+// Delete accepts a unique ID and deletes the port associated with it.
 func Delete(c *gophercloud.ServiceClient, id string) error {
 	_, err := perigee.Request("DELETE", deleteURL(c, id), perigee.Options{
 		MoreHeaders: c.Provider.AuthenticatedHeaders(),
diff --git a/openstack/networking/v2/ports/results.go b/openstack/networking/v2/ports/results.go
index 7e90d8d..cddb58d 100644
--- a/openstack/networking/v2/ports/results.go
+++ b/openstack/networking/v2/ports/results.go
@@ -5,11 +5,14 @@
 	"github.com/rackspace/gophercloud/pagination"
 )
 
+// IP is a sub-struct that represents an individual IP.
 type IP struct {
 	SubnetID  string `mapstructure:"subnet_id" json:"subnet_id"`
 	IPAddress string `mapstructure:"ip_address" json:"ip_address,omitempty"`
 }
 
+// Port represents a Neutron port. See package documentation for a top-level
+// description of what this is.
 type Port struct {
 	// UUID for the port.
 	ID string `mapstructure:"id" json:"id"`
@@ -45,11 +48,16 @@
 	BindingVNICType     string        `mapstructure:"binding:vnic_type" json:"binding:vnic_type"`
 }
 
+// PortPage is the page returned by a pager when traversing over a collection
+// of network ports.
 type PortPage struct {
 	pagination.LinkedPageBase
 }
 
-func (current PortPage) NextPageURL() (string, error) {
+// NextPageURL is invoked when a paginated collection of ports has reached
+// the end of a page and the pager seeks to traverse over a new one. In order
+// to do this, it needs to construct the next page's URL.
+func (p PortPage) NextPageURL() (string, error) {
 	type resp struct {
 		Links []struct {
 			Href string `mapstructure:"href"`
@@ -58,7 +66,7 @@
 	}
 
 	var r resp
-	err := mapstructure.Decode(current.Body, &r)
+	err := mapstructure.Decode(p.Body, &r)
 	if err != nil {
 		return "", err
 	}
@@ -76,14 +84,18 @@
 	return url, nil
 }
 
-func (r PortPage) IsEmpty() (bool, error) {
-	is, err := ExtractPorts(r)
+// IsEmpty checks whether a PortPage struct is empty.
+func (p PortPage) IsEmpty() (bool, error) {
+	is, err := ExtractPorts(p)
 	if err != nil {
 		return true, nil
 	}
 	return len(is) == 0, nil
 }
 
+// ExtractPorts accepts a Page struct, specifically a PortPage struct,
+// and extracts the elements into a slice of Port structs. In other words,
+// a generic collection is mapped into a relevant slice.
 func ExtractPorts(page pagination.Page) ([]Port, error) {
 	var resp struct {
 		Ports []Port `mapstructure:"ports" json:"ports"`
diff --git a/openstack/networking/v2/subnets/doc.go b/openstack/networking/v2/subnets/doc.go
index b15101b..43e8296 100644
--- a/openstack/networking/v2/subnets/doc.go
+++ b/openstack/networking/v2/subnets/doc.go
@@ -1 +1,10 @@
+// Package subnets contains functionality for working with Neutron subnet
+// resources. A subnet represents an IP address block that can be used to
+// assign IP addresses to virtual instances. Each subnet must have a CIDR and
+// must be associated with a network. IPs can either be selected from the whole
+// subnet CIDR or from allocation pools specified by the user.
+//
+// A subnet can also have a gateway, a list of DNS name servers, and host routes.
+// This information is pushed to instances whose interfaces are associated with
+// the subnet.
 package subnets
diff --git a/openstack/networking/v2/subnets/errors.go b/openstack/networking/v2/subnets/errors.go
index ca2df72..0db0a6e 100644
--- a/openstack/networking/v2/subnets/errors.go
+++ b/openstack/networking/v2/subnets/errors.go
@@ -7,9 +7,7 @@
 }
 
 var (
-	ErrNetworkIDRequired     = err("A network ID is required")
-	ErrCIDRRequired          = err("A valid CIDR is required")
-	ErrInvalidIPType         = err("An IP type must either be 4 or 6")
-	ErrCIDRNotUpdatable      = err("CIDR attributes cannot be updated")
-	ErrIPVersionNotUpdatable = err("IP Version attributes cannot be updated")
+	errNetworkIDRequired = err("A network ID is required")
+	errCIDRRequired      = err("A valid CIDR is required")
+	errInvalidIPType     = err("An IP type must either be 4 or 6")
 )
diff --git a/openstack/networking/v2/subnets/requests.go b/openstack/networking/v2/subnets/requests.go
index ff36765..5a07863 100644
--- a/openstack/networking/v2/subnets/requests.go
+++ b/openstack/networking/v2/subnets/requests.go
@@ -9,6 +9,18 @@
 	"github.com/rackspace/gophercloud/pagination"
 )
 
+func maybeString(original string) *string {
+	if original != "" {
+		return &original
+	}
+	return nil
+}
+
+// ListOpts allows the filtering and sorting of paginated collections through
+// the API. Filtering is achieved by passing in struct field values that map to
+// the subnet attributes you want to see returned. SortKey allows you to sort
+// by a particular subnet attribute. SortDir sets the direction, and is either
+// `asc' or `desc'. Marker and Limit are used for pagination.
 type ListOpts struct {
 	Name       string
 	EnableDHCP *bool
@@ -19,12 +31,18 @@
 	CIDR       string
 	ID         string
 	Limit      int
-	Page       string
-	PerPage    string
+	Marker     string
 	SortKey    string
 	SortDir    string
 }
 
+// List returns a Pager which allows you to iterate over a collection of
+// subnets. It accepts a ListOpts struct, which allows you to filter and sort
+// the returned collection for greater efficiency.
+//
+// Default policy settings return only those subnets that are owned by the tenant
+// who submits the request, unless the request is submitted by an user with
+// administrative rights.
 func List(c *gophercloud.ServiceClient, opts ListOpts) pagination.Pager {
 	// Build query parameters
 	q := make(map[string]string)
@@ -55,11 +73,8 @@
 	if opts.Limit != 0 {
 		q["limit"] = strconv.Itoa(opts.Limit)
 	}
-	if opts.Page != "" {
-		q["page"] = opts.Page
-	}
-	if opts.PerPage != "" {
-		q["per_page"] = opts.PerPage
+	if opts.Marker != "" {
+		q["marker"] = opts.Marker
 	}
 	if opts.SortKey != "" {
 		q["sort_key"] = opts.SortKey
@@ -68,15 +83,16 @@
 		q["sort_dir"] = opts.SortDir
 	}
 
-	u := ListURL(c) + utils.BuildQuery(q)
+	u := listURL(c) + utils.BuildQuery(q)
 	return pagination.NewPager(c, u, func(r pagination.LastHTTPResponse) pagination.Page {
 		return SubnetPage{pagination.LinkedPageBase(r)}
 	})
 }
 
+// Get retrieves a specific subnet based on its unique ID.
 func Get(c *gophercloud.ServiceClient, id string) (*Subnet, error) {
 	var s Subnet
-	_, err := perigee.Request("GET", GetURL(c, id), perigee.Options{
+	_, err := perigee.Request("GET", getURL(c, id), perigee.Options{
 		MoreHeaders: c.Provider.AuthenticatedHeaders(),
 		Results: &struct {
 			Subnet *Subnet `json:"subnet"`
@@ -89,19 +105,13 @@
 	return &s, nil
 }
 
-// maybeString returns nil for empty strings and nil for empty.
-func maybeString(original string) *string {
-	if original != "" {
-		return &original
-	}
-	return nil
-}
-
+// Valid IP types
 const (
 	IPv4 = 4
 	IPv6 = 6
 )
 
+// CreateOpts represents the attributes used when creating a new subnet.
 type CreateOpts struct {
 	// Required
 	NetworkID string
@@ -117,16 +127,18 @@
 	HostRoutes      []interface{}
 }
 
+// Create accepts a CreateOpts struct and creates a new subnet using the values
+// provided. You must remember to provide a valid NetworkID, CIDR and IP version.
 func Create(c *gophercloud.ServiceClient, opts CreateOpts) (*Subnet, error) {
 	// Validate required options
 	if opts.NetworkID == "" {
-		return nil, ErrNetworkIDRequired
+		return nil, errNetworkIDRequired
 	}
 	if opts.CIDR == "" {
-		return nil, ErrCIDRRequired
+		return nil, errCIDRRequired
 	}
 	if opts.IPVersion != 0 && opts.IPVersion != IPv4 && opts.IPVersion != IPv6 {
-		return nil, ErrInvalidIPType
+		return nil, errInvalidIPType
 	}
 
 	type subnet struct {
@@ -172,7 +184,7 @@
 	}
 
 	var res response
-	_, err := perigee.Request("POST", CreateURL(c), perigee.Options{
+	_, err := perigee.Request("POST", createURL(c), perigee.Options{
 		MoreHeaders: c.Provider.AuthenticatedHeaders(),
 		ReqBody:     &reqBody,
 		Results:     &res,
@@ -185,6 +197,7 @@
 	return res.Subnet, nil
 }
 
+// UpdateOpts represents the attributes used when updating an existing subnet.
 type UpdateOpts struct {
 	Name           string
 	GatewayIP      string
@@ -193,6 +206,8 @@
 	EnableDHCP     *bool
 }
 
+// Update accepts a UpdateOpts struct and updates an existing subnet using the
+// values provided.
 func Update(c *gophercloud.ServiceClient, id string, opts UpdateOpts) (*Subnet, error) {
 	type subnet struct {
 		Name           *string       `json:"name,omitempty"`
@@ -224,7 +239,7 @@
 	}
 
 	var res response
-	_, err := perigee.Request("PUT", UpdateURL(c, id), perigee.Options{
+	_, err := perigee.Request("PUT", updateURL(c, id), perigee.Options{
 		MoreHeaders: c.Provider.AuthenticatedHeaders(),
 		ReqBody:     &reqBody,
 		Results:     &res,
@@ -237,8 +252,9 @@
 	return res.Subnet, nil
 }
 
+// Delete accepts a unique ID and deletes the subnet associated with it.
 func Delete(c *gophercloud.ServiceClient, id string) error {
-	_, err := perigee.Request("DELETE", DeleteURL(c, id), perigee.Options{
+	_, err := perigee.Request("DELETE", deleteURL(c, id), perigee.Options{
 		MoreHeaders: c.Provider.AuthenticatedHeaders(),
 		OkCodes:     []int{204},
 	})
diff --git a/openstack/networking/v2/subnets/results.go b/openstack/networking/v2/subnets/results.go
index d916a1c..f89bb3b 100644
--- a/openstack/networking/v2/subnets/results.go
+++ b/openstack/networking/v2/subnets/results.go
@@ -5,11 +5,14 @@
 	"github.com/rackspace/gophercloud/pagination"
 )
 
+// AllocationPool is a sub-struct that represents an allocation pool
 type AllocationPool struct {
 	Start string `json:"start"`
 	End   string `json:"end"`
 }
 
+// Subnet represents a subnet. See package documentation for a top-level
+// description of what this is.
 type Subnet struct {
 	// UUID representing the subnet
 	ID string `mapstructure:"id" json:"id"`
@@ -35,11 +38,16 @@
 	TenantID string `mapstructure:"tenant_id" json:"tenant_id"`
 }
 
+// SubnetPage is the page returned by a pager when traversing over a collection
+// of subnets.
 type SubnetPage struct {
 	pagination.LinkedPageBase
 }
 
-func (current SubnetPage) NextPageURL() (string, error) {
+// NextPageURL is invoked when a paginated collection of subnets has reached
+// the end of a page and the pager seeks to traverse over a new one. In order
+// to do this, it needs to construct the next page's URL.
+func (p SubnetPage) NextPageURL() (string, error) {
 	type link struct {
 		Href string `mapstructure:"href"`
 		Rel  string `mapstructure:"rel"`
@@ -49,7 +57,7 @@
 	}
 
 	var r resp
-	err := mapstructure.Decode(current.Body, &r)
+	err := mapstructure.Decode(p.Body, &r)
 	if err != nil {
 		return "", err
 	}
@@ -67,14 +75,18 @@
 	return url, nil
 }
 
-func (r SubnetPage) IsEmpty() (bool, error) {
-	is, err := ExtractSubnets(r)
+// IsEmpty checks whether a SubnetPage struct is empty.
+func (p SubnetPage) IsEmpty() (bool, error) {
+	is, err := ExtractSubnets(p)
 	if err != nil {
 		return true, nil
 	}
 	return len(is) == 0, nil
 }
 
+// ExtractSubnets accepts a Page struct, specifically a SubnetPage struct,
+// and extracts the elements into a slice of Subnet structs. In other words,
+// a generic collection is mapped into a relevant slice.
 func ExtractSubnets(page pagination.Page) ([]Subnet, error) {
 	var resp struct {
 		Subnets []Subnet `mapstructure:"subnets" json:"subnets"`
diff --git a/openstack/networking/v2/subnets/urls.go b/openstack/networking/v2/subnets/urls.go
index fe20c53..ca70b66 100644
--- a/openstack/networking/v2/subnets/urls.go
+++ b/openstack/networking/v2/subnets/urls.go
@@ -2,32 +2,32 @@
 
 import "github.com/rackspace/gophercloud"
 
-const Version = "v2.0"
+const version = "v2.0"
 
-func ResourceURL(c *gophercloud.ServiceClient, id string) string {
-	return c.ServiceURL(Version, "subnets", id)
+func resourceURL(c *gophercloud.ServiceClient, id string) string {
+	return c.ServiceURL(version, "subnets", id)
 }
 
-func RootURL(c *gophercloud.ServiceClient) string {
-	return c.ServiceURL(Version, "subnets")
+func rootURL(c *gophercloud.ServiceClient) string {
+	return c.ServiceURL(version, "subnets")
 }
 
-func ListURL(c *gophercloud.ServiceClient) string {
-	return RootURL(c)
+func listURL(c *gophercloud.ServiceClient) string {
+	return rootURL(c)
 }
 
-func GetURL(c *gophercloud.ServiceClient, id string) string {
-	return ResourceURL(c, id)
+func getURL(c *gophercloud.ServiceClient, id string) string {
+	return resourceURL(c, id)
 }
 
-func CreateURL(c *gophercloud.ServiceClient) string {
-	return RootURL(c)
+func createURL(c *gophercloud.ServiceClient) string {
+	return rootURL(c)
 }
 
-func UpdateURL(c *gophercloud.ServiceClient, id string) string {
-	return ResourceURL(c, id)
+func updateURL(c *gophercloud.ServiceClient, id string) string {
+	return resourceURL(c, id)
 }
 
-func DeleteURL(c *gophercloud.ServiceClient, id string) string {
-	return ResourceURL(c, id)
+func deleteURL(c *gophercloud.ServiceClient, id string) string {
+	return resourceURL(c, id)
 }
diff --git a/openstack/networking/v2/subnets/urls_tests.go b/openstack/networking/v2/subnets/urls_tests.go
index eec5275..b04b432 100644
--- a/openstack/networking/v2/subnets/urls_tests.go
+++ b/openstack/networking/v2/subnets/urls_tests.go
@@ -7,38 +7,38 @@
 	th "github.com/rackspace/gophercloud/testhelper"
 )
 
-const Endpoint = "http://localhost:57909/"
+const endpoint = "http://localhost:57909/"
 
-func EndpointClient() *gophercloud.ServiceClient {
-	return &gophercloud.ServiceClient{Endpoint: Endpoint}
+func endpointClient() *gophercloud.ServiceClient {
+	return &gophercloud.ServiceClient{Endpoint: endpoint}
 }
 
 func TestListURL(t *testing.T) {
-	actual := ListURL(EndpointClient())
-	expected := Endpoint + "v2.0/subnets"
+	actual := listURL(endpointClient())
+	expected := endpoint + "v2.0/subnets"
 	th.AssertEquals(t, expected, actual)
 }
 
 func TestGetURL(t *testing.T) {
-	actual := GetURL(EndpointClient(), "foo")
-	expected := Endpoint + "v2.0/subnets/foo"
+	actual := getURL(endpointClient(), "foo")
+	expected := endpoint + "v2.0/subnets/foo"
 	th.AssertEquals(t, expected, actual)
 }
 
 func TestCreateURL(t *testing.T) {
-	actual := CreateURL(EndpointClient())
-	expected := Endpoint + "v2.0/subnets"
+	actual := createURL(endpointClient())
+	expected := endpoint + "v2.0/subnets"
 	th.AssertEquals(t, expected, actual)
 }
 
 func TestUpdateURL(t *testing.T) {
-	actual := UpdateURL(EndpointClient(), "foo")
-	expected := Endpoint + "v2.0/subnets/foo"
+	actual := updateURL(endpointClient(), "foo")
+	expected := endpoint + "v2.0/subnets/foo"
 	th.AssertEquals(t, expected, actual)
 }
 
 func TestDeleteURL(t *testing.T) {
-	actual := DeleteURL(EndpointClient(), "foo")
-	expected := Endpoint + "v2.0/subnets/foo"
+	actual := deleteURL(endpointClient(), "foo")
+	expected := endpoint + "v2.0/subnets/foo"
 	th.AssertEquals(t, expected, actual)
 }