Index: src/wp-includes/ms-functions.php
===================================================================
--- src/wp-includes/ms-functions.php	(revision 25448)
+++ src/wp-includes/ms-functions.php	(working copy)
@@ -2007,6 +2007,7 @@
  *     @type int       'spam'       Retrieve spam or non-spam sites. Default null, for any.
  *     @type int       'deleted'    Retrieve deleted or non-deleted sites. Default null, for any.
  *     @type int       'limit'      Number of sites to limit the query to. Default 100.
+ *     @type int       'offset'     Retrieve sites, excluding the first x sites. Used in combination with the limit parameter. Default 0.
  * }
  *
  * @return array An array of site data
@@ -2025,6 +2026,7 @@
 		'spam'       => null,
 		'deleted'    => null,
 		'limit'      => 100,
+		'offset'      => 0,
 	);
 
 	$args = wp_parse_args( $args, $defaults );
@@ -2052,8 +2054,13 @@
 	if ( isset( $args['deleted'] ) )
 		$query .= $wpdb->prepare( "AND deleted = %d ", $args['deleted'] );
 
-	if ( isset( $args['limit'] ) )
-		$query .= $wpdb->prepare( "LIMIT %d ", $args['limit'] );
+	if ( isset( $args['limit'] ) && intval( $args['limit'] ) > 0 ) {
+		if ( isset( $args['offset'] ) && intval( $args['offset'] ) > 0 ) {
+			$query .= $wpdb->prepare( "LIMIT %d , %d ", $args['offset'], $args['limit'] );
+		} else {
+			$query .= $wpdb->prepare( "LIMIT %d ", $args['limit'] );
+		}
+	}
 
 	$site_results = $wpdb->get_results( $query, ARRAY_A );
 
Index: tests/phpunit/tests/ms.php
===================================================================
--- tests/phpunit/tests/ms.php	(revision 25448)
+++ tests/phpunit/tests/ms.php	(working copy)
@@ -1033,7 +1033,6 @@
 	 * @ticket 14511
 	 */
 	function test_wp_get_sites() {
-		global $wpdb;
 		$this->factory->blog->create_many( 2, array( 'site_id' => 2, 'meta' => array( 'public' => 1 ) ) );
 		$this->factory->blog->create_many( 3, array( 'site_id' => 3, 'meta' => array( 'public' => 0 ) ) );
 
@@ -1069,6 +1068,29 @@
 	}
 
 	/**
+	 * @ticket 14511
+	 */
+	function test_wp_get_sites_limit_offset() {
+		// Create 4 more sites (in addition to the default one)
+		$this->factory->blog->create_many( 4, array( 'meta' => array( 'public' => 1 ) ) );
+
+		// Expect all 5 sites when no limit/offset is specified
+		$this->assertCount( 5, wp_get_sites() );
+
+		// Expect first 2 sites when using limit
+		$this->assertCount( 2, wp_get_sites( array( 'limit' => 2 ) ) );
+
+		// Expect only the last 3 sites when using offset of 2 (limit will default to 100)
+		$this->assertCount( 3, wp_get_sites( array( 'offset' => 2 ) ) );
+
+		// Expect only the last 1 site when using offset of 4 and limit of 2
+		$this->assertCount( 1, wp_get_sites( array( 'limit' => 2, 'offset' => 4 ) ) );
+
+		// Expect 0 sites when using an offset larger than the number of sites
+		$this->assertCount( 0, wp_get_sites( array( 'offset' => 20 ) ) );
+	}
+
+	/**
 	 * Test the 'archived' argument for wp_get_sites().
 	 *
 	 * archived is an ENUM, not an integer field.
